#pacman::p_install_gh("systats/binoculaR")
#devtools::install_github("strengejacke/sjlabelled",dependencies=TRUE)
#devtools::install_github("strengejacke/sjmisc",dependencies=TRUE)
#devtools::install_github("strengejacke/sjstats",dependencies=TRUE)
#devtools::install_github("strengejacke/ggeffects",dependencies=TRUE)
#devtools::install_github("strengejacke/sjPlot",dependencies=TRUE)
#devtools::install_github("lme4/lme4",dependencies=TRUE)
#pacman::p_install_gh("systats/binoculaR")
pacman::p_load(tidyverse, haven, magrittr, car, psych, sjPlot, sjstats, sjmisc, lme4, binoculaR, MuMIn)

Load in Data

arab4 <- read_spss("data/arab4.sav")
arab3 <- read_spss("data/arab3.sav")
# arab4 <- get(load(url("https://github.com/favstats/GodlyGovernance/raw/master/data/arab4.Rdata")))

Inspect Data

#b_select <- binoculaR::binoculaR(arab4)
#dput(b_select$var_codes)
#index <- c("country","wt" ,"sample" ,"a1", "q1", "q2", "q13", "q5182", 
#"q5184", "q6013", "q6014", "q6018", "q60118", "q605a", "q6061", "q6062", 
#"q6063", "q6064", "q6071", "q6074", "q6076", "q707", "q708", 
#"q7114", "q1001", "q1002", "q1003", "t1003", "q1004", "q1005", 
#"q609", "q6101", "q6106", "q1012", "q1012a", "q1016")
#
#arab4 %<>%
#  select(index)
#
#arab4
#view_df2(arab3, hide.progress = T)
# save(arab4, file = "data/arab4.Rdata")

Filter Data

arab4 %<>%
  filter(q1012 == 1) %>%#only Muslims
  mutate(sample = ifelse(is.na(sample) | sample == 1, 1, 2)) %>% 
  filter(sample != 2) #only non-refugees
arab3 %<>%
  filter(q1012 == 1) #only Muslims
arab3
arab4

Recode Data

Arab3

arab3 %<>% 
  mutate(cntry = sjmisc::to_label(country)) %>% 
  mutate(region = sjmisc::to_label(a1)) %>% 
  mutate(governorate = sjmisc::to_label(q1)) %>% 
  mutate(year = lubridate::year(date))
  # Dependent Variable
arab3 %<>% 
  mutate(islamistparties1 = ifelse(q518a2 > 5, NA, 5 - q518a2)) %>%
  mutate(islamistparties2 = ifelse(q518b2 > 5, NA, 5 - q518b2)) %>% 
  mutate(islamistparties = case_when(
        islamistparties1 == 1 ~ 1,
        islamistparties1 == 2 ~ 2,
        islamistparties1 == 3 ~ 3,
        islamistparties1 == 4 ~ 4,
        islamistparties2 == 1 ~ 1,
        islamistparties2 == 2 ~ 2,
        islamistparties2 == 3 ~ 3,
        islamistparties2 == 4 ~ 4)
    ) %>%  
  mutate(islamistgov = ifelse(q5184 > 5, NA, 5 - q5184)) %>% 
  mutate(religinterfere = ifelse(q6061 > 5, NA, q6061)) %>% 
  mutate(religleaders = ifelse(q6062 > 5, NA, 5 - q6062)) %>% 
  mutate(religleadersinfl = ifelse(q6063 > 5, NA, 5 - q6063)) %>%
  mutate(seperation = ifelse(q6064 > 5, NA, q6064)) %>% 
  mutate(religparty = Recode(q605a, "1 = 1;
                                     2 = 1;
                                     3 = 0;
                                     4 = 0;
                                     5 = 0;
                                    8 = 0;
                                    9 = NA")) %>% 
  mutate(religparty2 = Recode(q605a, "1 = 5;
                                      2 = 4;
                                      3 = 2;
                                      4 = 1;
                                      5 = 3;
                                     8 = NA;
                                     9 = NA"))
ifelse4cat_rec <- function(variable) {
  recoded <- ifelse(variable == 0 | variable > 5, NA, 5 - variable)
  return(recoded)
}
arab3 %<>% 
  mutate(female = ifelse(sex == 2, 1, 0)) %>% 
  mutate(work = ifelse(q1004 == 0 | q1004 > 5, NA, abs(q1004 - 2))) %>% 
  mutate(income = ifelse4cat_rec(q1016)) %>% 
  mutate(age = ifelse(q1001 == 0 | q1001 == 9999, NA, q1001)) %>% 
  mutate(educ = case_when(
        q1003 == 0 ~ NA_real_,
        q1003 == 99 ~ NA_real_,
        q1003 == 5 ~ 4,
        q1003 == 6 ~ 5,
        q1003 == 7 ~ 6,
        q1003yem == 0 ~ NA_real_,
        q1003yem == 99 ~ NA_real_,
        q1003yem == 4 ~ 3,
        q1003yem == 5 ~ 4,
        q1003yem == 6 ~ 5,
        q1003yem == 7 ~ 5,
        q1003yem == 8 ~ 6,
        q1003t == 0 ~ NA_real_,
        q1003t == 99 ~ NA_real_,
        q1003t == 1 ~ 1,
        q1003t == 2 ~ 2,
        q1003t == 3 ~ 3,
        q1003t == 4 ~ 4,
        q1003t == 5 ~ 5,
        q1003t == 6 ~ 6,
    TRUE ~ as.numeric(q1003))
    ) %>% 
  mutate(globalism = ifelse(q701b == 0 | q701b > 5, NA, q701b)) %>% 
  mutate(pray = ifelse(q6101 == 0 | q6101 > 5, NA, 6 - q6101)) %>% 
  mutate(quran = ifelse(q6106 == 0 | q6106 > 5, NA, 6 - q6106)) %>%
  mutate(womanwork = ifelse(q6012 == 0 | q6012 > 5, NA, q6012)) %>% 
  mutate(womenleader = ifelse4cat_rec(q6013)) %>% 
  mutate(womeneduc = ifelse4cat_rec(q6014)) %>% 
  mutate(nodemoc = ifelse(q6071 == 0 | q6071 > 5, NA, q6071)) %>% 
  mutate(genderapartuni = ifelse4cat_rec(q6074)) %>% 
  mutate(coverup = ifelse4cat_rec(q6076)) %>% 
  select(cntry, year, region, governorate, islamistparties , islamistgov, religinterfere, religleaders, religleadersinfl, seperation, religparty, religparty2, female, work, income,  age, educ, globalism, pray, quran, womanwork, womenleader, womeneduc, nodemoc, genderapartuni, coverup)

Arab4

table(arab4$country)

   1    5    8   10   13   15   21 
1199 1146 1172  615 1199 1177 1200 
arab4 %<>% 
  mutate(cntry = sjmisc::to_label(country)) %>% 
  mutate(region = sjmisc::to_label(a1)) %>% 
  mutate(governorate = sjmisc::to_label(q1)) %>% 
  mutate(year = 2016)#%>%
#  mutate(district = sjmisc::to_label(q2)) 
# Dependent Variable
arab4 %<>% 
  mutate(islamistparties = ifelse(q5182 > 5, NA, 5 - q5182)) %>% 
  mutate(islamistgov = ifelse(q5184 > 5, NA, 5 - q5184)) %>% 
  mutate(religinterfere = ifelse(q6061 > 5, NA, q6061)) %>% 
  mutate(religleaders = ifelse(q6062 > 5, NA, 5 - q6062)) %>% 
  mutate(religleadersinfl = ifelse(q6063 > 5, NA, 5 - q6063)) %>%
  mutate(seperation = ifelse(q6064 > 5, NA, q6064)) %>% 
  mutate(religparty = Recode(q605a, "1 = 1;
                                     2 = 1;
                                     3 = 0;
                                     4 = 0;
                                     5 = 0;
                                    98 = 0;
                                    99 = NA")) %>% 
  mutate(religparty2 = Recode(q605a, "1 = 5;
                                      2 = 4;
                                      3 = 2;
                                      4 = 1;
                                      5 = 3;
                                     98 = NA;
                                     99 = NA"))
arab4 %<>% 
  mutate(female = ifelse(q1002 == 2, 1, 0)) %>% 
  mutate(work = ifelse(q1004 == 0 | q1004 > 5, NA, abs(q1004 - 2))) %>% 
  mutate(income = ifelse4cat_rec(q1016)) %>% 
  mutate(age = ifelse(q1001 == 0 | q1001 == 9999, NA, q1001)) %>% 
  mutate(educ = case_when(
        q1003 == 0 ~ NA_real_,
        q1003 == 98 ~ NA_real_,
        q1003 == 99 ~ NA_real_,
        q1003 == 5 ~ 4,
        q1003 == 6 ~ 5,
        q1003 == 7 ~ 6,
        t1003 == 0 ~ NA_real_,
        t1003 == 98 ~ NA_real_,
        t1003 == 99 ~ NA_real_,
        t1003 == 3 ~ 3,
        t1003 == 4 ~ 4,
        t1003 == 5 ~ 5,
        t1003 == 6 ~ 6,
    TRUE ~ as.numeric(q1003))
    ) %>% 
  mutate(globalism = ifelse(q701b == 0 | q701b > 5, NA, q701b)) %>% 
  mutate(pray = ifelse(q6101 == 0 | q6101 > 5, NA, 6 - q6101)) %>% 
  mutate(quran = ifelse(q6106 == 0 | q6106 > 5, NA, 6 - q6106)) %>% 
  mutate(womanwork = ifelse(q6012 == 0 | q6012 > 5, NA, q6012)) %>% 
  mutate(womenleader = ifelse4cat_rec(q6013)) %>% 
  mutate(womeneduc = ifelse4cat_rec(q6014)) %>% 
  mutate(nodemoc = ifelse(q6071 == 0 | q6071 > 5, NA, q6071)) %>% 
  mutate(genderapartuni = ifelse4cat_rec(q6074)) %>% 
  mutate(coverup = ifelse4cat_rec(q6076)) %>% 
  select(cntry, year, region, governorate , islamistparties , islamistgov, religinterfere, religleaders, religleadersinfl, seperation, religparty, religparty2, female, work, income,  age, educ, globalism, pray, quran, womanwork, womenleader, womeneduc, nodemoc, genderapartuni, coverup)

Merging

Factor Analysis

# f1 <- arab %>% 
#   select(islamistparties, islamistgov, 
#          religleaders, religleadersinfl) %>%
#   # na.omit() %>% 
#   psych::fa(1, rotate = "varimax",   
#         fm = "pa",
#         scores = "regression",
#         weight = na.omit(arab$wt)  )         
# fa.diagram(f1)                                  
# f1              
f2 <- arab %>% 
  select(islamistparties, islamistgov, 
         religleaders, religleadersinfl) %>% 
  psych::pca(weight = arab$wt) 
arab %>% 
  select(islamistparties, islamistgov, 
         religleaders, religleadersinfl) %>% 
  alpha() 

Reliability analysis   
Call: alpha(x = .)

  raw_alpha std.alpha G6(smc) average_r S/N    ase mean   sd
       0.7       0.7    0.66      0.37 2.3 0.0034    2 0.71

 lower alpha upper     95% confidence boundaries
0.69 0.7 0.71 

 Reliability if an item is dropped:
                 raw_alpha std.alpha G6(smc) average_r S/N alpha se
islamistparties       0.65      0.65    0.58      0.39 1.9   0.0042
islamistgov           0.65      0.66    0.58      0.39 1.9   0.0041
religleaders          0.60      0.60    0.51      0.33 1.5   0.0046
religleadersinfl      0.64      0.64    0.54      0.37 1.7   0.0042

 Item statistics 
                     n raw.r std.r r.cor r.drop mean   sd
islamistparties  20198  0.72  0.71  0.55   0.46  1.7 0.95
islamistgov      20135  0.73  0.71  0.54   0.46  1.7 1.02
religleaders     20431  0.75  0.76  0.66   0.53  2.3 0.92
religleadersinfl 20524  0.72  0.73  0.60   0.48  2.2 0.89

Non missing response frequency for each item
                    1    2    3    4 5 miss
islamistparties  0.59 0.19 0.15 0.07 0 0.08
islamistgov      0.59 0.17 0.14 0.10 0 0.08
religleaders     0.21 0.38 0.31 0.10 0 0.07
religleadersinfl 0.24 0.42 0.26 0.08 0 0.06
arab %>% 
  select(islamistparties, islamistgov, 
         religleaders, religleadersinfl) %>% 
  KMO() 
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = .)
Overall MSA =  0.68
MSA for each item = 
 islamistparties      islamistgov     religleaders religleadersinfl 
            0.71             0.72             0.66             0.66 
arab4 %>% 
  select(islamistparties, islamistgov, 
         religleaders, religleadersinfl,
         religparty2, seperation,
         religinterfere) %>% 
  na.omit() %>% 
  cor()  
                 islamistparties islamistgov religleaders religleadersinfl
islamistparties        1.0000000   0.3760955    0.3274069        0.2595854
islamistgov            0.3760955   1.0000000    0.3180997        0.3059820
religleaders           0.3274069   0.3180997    1.0000000        0.5628358
religleadersinfl       0.2595854   0.3059820    0.5628358        1.0000000
religparty2            0.2625742   0.2409189    0.3812004        0.3120300
seperation             0.1409401   0.2186956    0.3190967        0.2944263
religinterfere         0.1393481   0.1283822    0.2070613        0.2539891
                 religparty2 seperation religinterfere
islamistparties    0.2625742  0.1409401      0.1393481
islamistgov        0.2409189  0.2186956      0.1283822
religleaders       0.3812004  0.3190967      0.2070613
religleadersinfl   0.3120300  0.2944263      0.2539891
religparty2        1.0000000  0.2819491      0.1671423
seperation         0.2819491  1.0000000      0.2725233
religinterfere     0.1671423  0.2725233      1.0000000
# arab <- predict.psych(f1, arab %>% 
#   select(islamistparties, islamistgov, 
#          religleaders, religleadersinfl)) %>% 
#   tbl_df() %>% 
#   cbind(arab) %>% 
#   mutate(islamism_fa = PA1)
arab <- predict.psych(f2, arab %>% 
  select(islamistparties, islamistgov, 
         religleaders, religleadersinfl)) %>% 
  tbl_df() %>% 
  transmute(islamism = PC1) %>% 
  cbind(arab) 
#%>% 
#  ggplot(aes(islamism)) +
#  geom_histogram() +
#  facet_wrap(~cntry, scales = "free")
#sjPlot::view_df(arab, show.frq = T, show.prc = T)
# 
# cor.test(arab$PC1, arab$PA1)

Creating indices

Regression

model1 <- lme4::lmer(islamism ~ female + work + income + age + educ + globalism + antiwestern + personalpiety + patriarchalvalues + liberalislam + year_2012 + year_2013 + year_2014 + (1|cntry), data = arab_reg, weights = wt)
texreg::screenreg(model1)

=====================================
                        Model 1      
-------------------------------------
(Intercept)                 -0.18    
                            (0.11)   
female                       0.07 ***
                            (0.02)   
work                        -0.06 ***
                            (0.02)   
income                       0.00    
                            (0.01)   
age                         -0.00 ***
                            (0.00)   
educ                        -0.03 ***
                            (0.01)   
globalism                    0.08 ***
                            (0.01)   
antiwestern                 -0.06 *  
                            (0.03)   
personalpiety                0.54 ***
                            (0.04)   
patriarchalvalues            0.76 ***
                            (0.04)   
liberalislam                -1.04 ***
                            (0.04)   
year_2012                    0.00    
                            (0.04)   
year_2013                    0.18 ***
                            (0.02)   
year_2014                   -0.08    
                            (0.09)   
-------------------------------------
AIC                      33078.64    
BIC                      33197.69    
Log Likelihood          -16523.32    
Num. obs.                12591       
Num. groups: cntry          12       
Var: cntry (Intercept)       0.10    
Var: Residual                0.69    
=====================================
*** p < 0.001, ** p < 0.01, * p < 0.05
model1 <- arab_reg %>% 
  lme4::lmer(islamism ~ female + work + income + age + educ + globalism + pray + quran + womanwork + womenleader + womeneduc + nodemoc + genderapartuni + coverup + (1|cntry/year), data = .)
texreg::screenreg(model1)

==========================================
                             Model 1      
------------------------------------------
(Intercept)                      33.38 ***
                                 (2.54)   
female                            1.89 ***
                                 (0.38)   
work                             -1.31 ***
                                 (0.38)   
income                            0.28    
                                 (0.18)   
age                              -1.02 ***
                                 (0.19)   
educ                             -0.74 ***
                                 (0.20)   
globalism                         1.63 ***
                                 (0.18)   
pray                              1.31 ***
                                 (0.20)   
quran                             2.05 ***
                                 (0.19)   
womanwork                         0.78 ***
                                 (0.22)   
womenleader                       2.40 ***
                                 (0.18)   
womeneduc                         2.14 ***
                                 (0.20)   
nodemoc                          -3.63 ***
                                 (0.21)   
genderapartuni                   -4.56 ***
                                 (0.22)   
coverup                          -0.82 ***
                                 (0.18)   
------------------------------------------
AIC                          118239.29    
BIC                          118374.48    
Log Likelihood               -59101.64    
Num. obs.                     13499       
Num. groups: year:cntry          19       
Num. groups: cntry               12       
Var: year:cntry (Intercept)      14.12    
Var: cntry (Intercept)           37.00    
Var: Residual                   369.66    
==========================================
*** p < 0.001, ** p < 0.01, * p < 0.05
plot_model(model1, sort.est = T, show.values = T, show.p = T, value.offset = 0.5)
Computing p-values via Wald-statistics approximation (treating t as Wald z).

plot_model(model1, terms = c("nodemoc", "female"), type = "pred")
Note: uncertainty of the random effects parameters are not taken into account for confidence intervals.

model2 <- arab_reg %>% 
  lme4::lmer(islamism ~ female + work + income + age + educ + globalism + pray + quran + womanwork + womenleader + womeneduc + nodemoc + genderapartuni + coverup + nodemoc*quran + (1|cntry/year), data = .)
texreg::screenreg(model2)

==========================================
                             Model 1      
------------------------------------------
(Intercept)                      35.34 ***
                                 (3.22)   
female                            1.89 ***
                                 (0.38)   
work                             -1.31 ***
                                 (0.38)   
income                            0.28    
                                 (0.18)   
age                              -1.02 ***
                                 (0.19)   
educ                             -0.74 ***
                                 (0.20)   
globalism                         1.63 ***
                                 (0.18)   
pray                              1.32 ***
                                 (0.20)   
quran                             1.53 ** 
                                 (0.56)   
womanwork                         0.79 ***
                                 (0.22)   
womenleader                       2.40 ***
                                 (0.18)   
womeneduc                         2.14 ***
                                 (0.20)   
nodemoc                          -4.32 ***
                                 (0.72)   
genderapartuni                   -4.55 ***
                                 (0.22)   
coverup                          -0.82 ***
                                 (0.18)   
quran:nodemoc                     0.18    
                                 (0.18)   
------------------------------------------
AIC                          118241.91    
BIC                          118384.60    
Log Likelihood               -59101.95    
Num. obs.                     13499       
Num. groups: year:cntry          19       
Num. groups: cntry               12       
Var: year:cntry (Intercept)      14.13    
Var: cntry (Intercept)           37.02    
Var: Residual                   369.66    
==========================================
*** p < 0.001, ** p < 0.01, * p < 0.05
view_df2 <- function (x, weight.by = NULL, altr.row.col = TRUE, show.id = TRUE, 
  show.type = FALSE, show.values = TRUE, show.string.values = FALSE, 
  show.labels = TRUE, show.frq = FALSE, show.prc = FALSE, 
  show.wtd.frq = FALSE, show.wtd.prc = FALSE, show.na = FALSE, 
  max.len = 15, sort.by.name = FALSE, wrap.labels = 50, hide.progress = FALSE, 
  CSS = NULL, encoding = NULL, file = NULL, use.viewer = TRUE, 
  no.output = FALSE, remove.spaces = TRUE) 
{
  get.encoding <- function(encoding, data = NULL) {
  if (is.null(encoding)) {
    if (!is.null(data) && is.data.frame(data)) {
      # get variable label
      labs <- sjlabelled::get_label(data[[1]])
      # check if vectors of data frame have
      # any valid label. else, default to utf-8
      if (!is.null(labs) && is.character(labs))
        encoding <- Encoding(sjlabelled::get_label(data[[1]]))
      else
        encoding <- "UTF-8"
      # unknown encoding? default to utf-8
      if (encoding == "unknown") encoding <- "UTF-8"
    } else if (.Platform$OS.type == "unix")
      encoding <- "UTF-8"
    else
      encoding <- "Windows-1252"
  }
  return(encoding)
}

  has_value_labels <- function(x) {
  !(is.null(attr(x, "labels", exact = T)) && is.null(attr(x, "value.labels", exact = T)))
}

  sju.rmspc <- function(html.table) {
  cleaned <- gsub("      <", "<", html.table, fixed = TRUE, useBytes = TRUE)
  cleaned <- gsub("    <", "<", cleaned, fixed = TRUE, useBytes = TRUE)
  cleaned <- gsub("  <", "<", cleaned, fixed = TRUE, useBytes = TRUE)
  return(cleaned)
  }
  
  frq.value <- function(index, x, df.val, weights = NULL) {
  valstring <- ""
  # check if we have a valid index
  if (index <= ncol(x) && !is.null(df.val[[index]])) {
    # do we have weights?
    if (!is.null(weights))
      variab <- sjstats::weight(x[[index]], weights)
    else
      variab <- x[[index]]
    # create frequency table. same function as for
    # sjt.frq and sjp.frq
    ftab <- create.frq.df(variab, 20)$mydat$frq
    # remove last value, which is N for NA
    if (length(ftab) == 1 && is.na(ftab)) {
      valstring <- "<NA>"
    } else {
      for (i in 1:(length(ftab) - 1)) {
        valstring <- paste0(valstring, ftab[i])
        if (i < length(ftab)) valstring <- paste0(valstring, "<br>")
      }
    }
  } else {
    valstring <- ""
  }
  return(valstring)
}

prc.value <- function(index, x, df.val, weights = NULL) {
  valstring <- ""
  # check for valid indices
  if (index <= ncol(x) && !is.null(df.val[[index]])) {
    # do we have weights?
    if (!is.null(weights))
      variab <- sjstats::weight(x[[index]], weights)
    else
      variab <- x[[index]]
    # create frequency table, but only get valid percentages
    ftab <- create.frq.df(variab, 20)$mydat$valid.prc
    # remove last value, which is a NA dummy
    if (length(ftab) == 1 && is.na(ftab)) {
      valstring <- "<NA>"
    } else {
      for (i in 1:(length(ftab) - 1)) {
        valstring <- paste0(valstring, sprintf("%.2f", ftab[i]))
        if (i < length(ftab)) valstring <- paste0(valstring, "<br>")
      }
    }
  } else {
    valstring <- ""
  }
  return(valstring)
}
  
  encoding <- get.encoding(encoding, x)
  if (!is.data.frame(x)) 
    stop("Parameter needs to be a data frame!", call. = FALSE)
  df.var <- sjlabelled::get_label(x)
  df.val <- sjlabelled::get_labels(x)
  colcnt <- ncol(x)
  id <- seq_len(colcnt)
  if (sort.by.name) 
    id <- id[order(colnames(x))]
  tag.table <- "table"
  tag.thead <- "thead"
  tag.tdata <- "tdata"
  tag.arc <- "arc"
  tag.caption <- "caption"
  tag.omit <- "omit"
  css.table <- "border-collapse:collapse; border:none;"
  css.thead <- "border-bottom:double; font-style:italic; font-weight:normal; padding:0.2cm; text-align:left; vertical-align:top;"
  css.tdata <- "padding:0.2cm; text-align:left; vertical-align:top;"
  css.arc <- "background-color:#eeeeee"
  css.caption <- "font-weight: bold; text-align:left;"
  css.omit <- "color:#999999;"
  if (!is.null(CSS)) {
    if (!is.null(CSS[["css.table"]])) 
      css.table <- ifelse(substring(CSS[["css.table"]], 
        1, 1) == "+", paste0(css.table, substring(CSS[["css.table"]], 
        2)), CSS[["css.table"]])
    if (!is.null(CSS[["css.thead"]])) 
      css.thead <- ifelse(substring(CSS[["css.thead"]], 
        1, 1) == "+", paste0(css.thead, substring(CSS[["css.thead"]], 
        2)), CSS[["css.thead"]])
    if (!is.null(CSS[["css.tdata"]])) 
      css.tdata <- ifelse(substring(CSS[["css.tdata"]], 
        1, 1) == "+", paste0(css.tdata, substring(CSS[["css.tdata"]], 
        2)), CSS[["css.tdata"]])
    if (!is.null(CSS[["css.arc"]])) 
      css.arc <- ifelse(substring(CSS[["css.arc"]], 1, 
        1) == "+", paste0(css.arc, substring(CSS[["css.arc"]], 
        2)), CSS[["css.arc"]])
    if (!is.null(CSS[["css.caption"]])) 
      css.caption <- ifelse(substring(CSS[["css.caption"]], 
        1, 1) == "+", paste0(css.caption, substring(CSS[["css.caption"]], 
        2)), CSS[["css.caption"]])
    if (!is.null(CSS[["css.omit"]])) 
      css.omit <- ifelse(substring(CSS[["css.omit"]], 
        1, 1) == "+", paste0(css.omit, substring(CSS[["css.omit"]], 
        2)), CSS[["css.omit"]])
  }
  page.style <- sprintf("<style>\nhtml, body { background-color: white; }\n%s { %s }\n.%s { %s }\n.%s { %s }\n.%s { %s }\n%s { %s }\n.%s { %s }\n</style>", 
    tag.table, css.table, tag.thead, css.thead, tag.tdata, 
    css.tdata, tag.arc, css.arc, tag.caption, css.caption, 
    tag.omit, css.omit)
  toWrite <- sprintf("<html>\n<head>\n<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n%s\n</head>\n<body>\n", 
    encoding, page.style)
  page.content <- sprintf("<table>\n  <caption>Data frame: %s</caption>\n", 
    deparse(substitute(x)))
  page.content <- paste0(page.content, "  <tr>\n    ")
  if (show.id) 
    page.content <- paste0(page.content, "<th class=\"thead\">ID</th>")
  page.content <- paste0(page.content, "<th class=\"thead\">Name</th>")
  if (show.type) 
    page.content <- paste0(page.content, "<th class=\"thead\">Type</th>")
  page.content <- paste0(page.content, "<th class=\"thead\">Label</th>")
  if (show.na) 
    page.content <- paste0(page.content, "<th class=\"thead\">missings</th>")
  if (show.values) 
    page.content <- paste0(page.content, "<th class=\"thead\">Values</th>")
  if (show.labels) 
    page.content <- paste0(page.content, "<th class=\"thead\">Value Labels</th>")
  if (show.frq) 
    page.content <- paste0(page.content, "<th class=\"thead\">Freq.</th>")
  if (show.prc) 
    page.content <- paste0(page.content, "<th class=\"thead\">%</th>")
  if (show.wtd.frq) 
    page.content <- paste0(page.content, "<th class=\"thead\">weighted Freq.</th>")
  if (show.wtd.prc) 
    page.content <- paste0(page.content, "<th class=\"thead\">weighted %</th>")
  page.content <- paste0(page.content, "\n  </tr>\n")
  if (!hide.progress) 
    pb <- utils::txtProgressBar(min = 0, max = colcnt, style = 3)
  for (ccnt in seq_len(colcnt)) {
    index <- id[ccnt]
    arcstring <- ""
    if (altr.row.col) 
      arcstring <- ifelse(sjmisc::is_even(ccnt), " arc", 
        "")
    page.content <- paste0(page.content, "  <tr>\n")
    if (show.id) 
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%i</td>\n", 
        arcstring, index))
    if (!is.list(x[[index]]) && !is.null(sjlabelled::get_note(x[[index]]))) 
      td.title.tag <- sprintf(" title=\"%s\"", sjlabelled::get_note(x[[index]]))
    else td.title.tag <- ""
    page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\"%s>%s</td>\n", 
      arcstring, td.title.tag, colnames(x)[index]))
    if (show.type) {
      vartype <- sjmisc::var_type(x[[index]])
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, vartype))
    }
    if (index <= length(df.var)) {
      varlab <- df.var[index]
      if (!is.null(wrap.labels)) {
        varlab <- sjmisc::word_wrap(varlab, wrap.labels, 
          "<br>")
      }
    }
    else {
      varlab <- "<NA>"
    }
    page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
      arcstring, varlab))
    if (show.na) {
      if (is.list(x[[index]])) {
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\"><span class=\"omit\">&lt;list&gt;</span></td>\n", 
          arcstring))
      }
      else {
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%i (%.2f%%)</td>\n", 
          arcstring, sum(is.na(x[[index]]), na.rm = T), 
          100 * sum(is.na(x[[index]]), na.rm = T)/nrow(x)))
      }
    }
    if (is.numeric(x[[index]]) && !has_value_labels(x[[index]])) {
      if (show.values || show.labels) {
        valstring <- paste0(sprintf("%a", range(x[[index]], 
          na.rm = T)), collapse = "-")
        if (show.values && show.labels) {
          colsp <- " colspan=\"2\""
          valstring <- paste0("<em>range: ", valstring, 
            "</em>")
        }
        else {
          colsp <- ""
        }
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\"%s>%s</td>\n", 
          arcstring, colsp, valstring))
      }
    }
    else {
      if (show.values) {
        valstring <- ""
        if (index <= ncol(x)) {
          if (is.list(x[[index]])) {
            valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
          }
          else {
            vals <- sjlabelled::get_values(x[[index]])
            if (!is.null(vals)) {
              loop <- na.omit(seq_len(length(vals))[1:max.len])
              for (i in loop) {
                valstring <- paste0(valstring, vals[i])
                if (i < length(vals)) 
                  valstring <- paste0(valstring, "<br>")
              }
              if (max.len < length(vals)) 
                valstring <- paste0(valstring, "<span class=\"omit\">&lt;...&gt;</span>")
            }
          }
        }
        else {
          valstring <- "<NA>"
        }
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
          arcstring, valstring))
      }
      if (show.labels) {
        valstring <- ""
        if (index <= length(df.val)) {
          if (is.list(x[[index]])) {
            valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
          }
          else {
            vals <- df.val[[index]]
            if (!is.null(vals)) 
              vals <- na.omit(vals)
            if (is.character(x[[index]]) && !is.null(vals) && 
              !sjmisc::is_empty(vals)) {
              if (show.string.values) 
                vals <- sort(vals)
              else vals <- "<span class=\"omit\" title =\"'show.string.values = TRUE' to show values.\">&lt;output omitted&gt;</span>"
            }
            if (!is.null(vals)) {
              loop <- na.omit(seq_len(length(vals))[1:max.len])
              for (i in loop) {
                valstring <- paste0(valstring, vals[i])
                if (i < length(vals)) 
                  valstring <- paste0(valstring, "<br>")
              }
              if (max.len < length(vals)) 
                valstring <- paste0(valstring, "<span class=\"omit\">&lt;... truncated&gt;</span>")
            }
          }
        }
        else {
          valstring <- "<NA>"
        }
        page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
          arcstring, valstring))
      }
    }
    if (show.frq) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- frq.value(index, x, df.val)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (show.prc) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- prc.value(index, x, df.val)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (show.wtd.frq && !is.null(weight.by)) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- frq.value(index, x, df.val, weight.by)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (show.prc && !is.null(weight.by)) {
      if (is.list(x[[index]])) 
        valstring <- "<span class=\"omit\">&lt;list&gt;</span>"
      else valstring <- prc.value(index, x, df.val, weight.by)
      page.content <- paste0(page.content, sprintf("    <td class=\"tdata%s\">%s</td>\n", 
        arcstring, valstring))
    }
    if (!hide.progress) 
      utils::setTxtProgressBar(pb, ccnt)
    page.content <- paste0(page.content, "  </tr>\n")
  }
  if (!hide.progress) 
    close(pb)
  page.content <- paste(page.content, "</table>", sep = "\n")
  toWrite <- paste0(toWrite, sprintf("%s\n</body></html>", 
    page.content))
  knitr <- page.content
  knitr <- gsub("class=", "style=", knitr, fixed = TRUE, useBytes = TRUE)
  knitr <- gsub("<table", sprintf("<table style=\"%s\"", css.table), 
    knitr, fixed = TRUE, useBytes = TRUE)
  knitr <- gsub(tag.tdata, css.tdata, knitr, fixed = TRUE, 
    useBytes = TRUE)
  knitr <- gsub(tag.thead, css.thead, knitr, fixed = TRUE, 
    useBytes = TRUE)
  knitr <- gsub(tag.arc, css.arc, knitr, fixed = TRUE, useBytes = TRUE)
  if (remove.spaces) {
    knitr <- sju.rmspc(knitr)
    toWrite <- sju.rmspc(toWrite)
    page.content <- sju.rmspc(page.content)
  }
  structure(class = c("sjTable", "view_df"), list(page.style = page.style, 
    page.content = page.content, output.complete = toWrite, 
    header = NULL, knitr = knitr, file = file, show = !no.output, 
    use.viewer = use.viewer))
}

view_df2(arab4, hide.progress = T)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyfQ0KI3BhY21hbjo6cF9pbnN0YWxsX2doKCJzeXN0YXRzL2Jpbm9jdWxhUiIpDQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJzdHJlbmdlamFja2Uvc2psYWJlbGxlZCIsZGVwZW5kZW5jaWVzPVRSVUUpDQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJzdHJlbmdlamFja2Uvc2ptaXNjIixkZXBlbmRlbmNpZXM9VFJVRSkNCiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInN0cmVuZ2VqYWNrZS9zanN0YXRzIixkZXBlbmRlbmNpZXM9VFJVRSkNCiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoInN0cmVuZ2VqYWNrZS9nZ2VmZmVjdHMiLGRlcGVuZGVuY2llcz1UUlVFKQ0KI2RldnRvb2xzOjppbnN0YWxsX2dpdGh1Yigic3RyZW5nZWphY2tlL3NqUGxvdCIsZGVwZW5kZW5jaWVzPVRSVUUpDQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJsbWU0L2xtZTQiLGRlcGVuZGVuY2llcz1UUlVFKQ0KI3BhY21hbjo6cF9pbnN0YWxsX2doKCJzeXN0YXRzL2Jpbm9jdWxhUiIpDQoNCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgaGF2ZW4sIG1hZ3JpdHRyLCBjYXIsIHBzeWNoLCBzalBsb3QsIHNqc3RhdHMsIHNqbWlzYywgbG1lNCwgYmlub2N1bGFSLCBNdU1JbikNCg0KDQpgYGANCg0KIyBMb2FkIGluIERhdGENCg0KYGBge3J9DQphcmFiNCA8LSByZWFkX3Nwc3MoImRhdGEvYXJhYjQuc2F2IikNCmFyYWIzIDwtIHJlYWRfc3BzcygiZGF0YS9hcmFiMy5zYXYiKQ0KDQojIGFyYWI0IDwtIGdldChsb2FkKHVybCgiaHR0cHM6Ly9naXRodWIuY29tL2ZhdnN0YXRzL0dvZGx5R292ZXJuYW5jZS9yYXcvbWFzdGVyL2RhdGEvYXJhYjQuUmRhdGEiKSkpDQoNCg0KYGBgDQoNCiMgSW5zcGVjdCBEYXRhDQoNCmBgYHtyfQ0KI2Jfc2VsZWN0IDwtIGJpbm9jdWxhUjo6Ymlub2N1bGFSKGFyYWI0KQ0KI2RwdXQoYl9zZWxlY3QkdmFyX2NvZGVzKQ0KDQojaW5kZXggPC0gYygiY291bnRyeSIsInd0IiAsInNhbXBsZSIgLCJhMSIsICJxMSIsICJxMiIsICJxMTMiLCAicTUxODIiLCANCiMicTUxODQiLCAicTYwMTMiLCAicTYwMTQiLCAicTYwMTgiLCAicTYwMTE4IiwgInE2MDVhIiwgInE2MDYxIiwgInE2MDYyIiwgDQojInE2MDYzIiwgInE2MDY0IiwgInE2MDcxIiwgInE2MDc0IiwgInE2MDc2IiwgInE3MDciLCAicTcwOCIsIA0KIyJxNzExNCIsICJxMTAwMSIsICJxMTAwMiIsICJxMTAwMyIsICJ0MTAwMyIsICJxMTAwNCIsICJxMTAwNSIsIA0KIyJxNjA5IiwgInE2MTAxIiwgInE2MTA2IiwgInExMDEyIiwgInExMDEyYSIsICJxMTAxNiIpDQojDQojYXJhYjQgJTw+JQ0KIyAgc2VsZWN0KGluZGV4KQ0KIw0KI2FyYWI0DQojdmlld19kZjIoYXJhYjMsIGhpZGUucHJvZ3Jlc3MgPSBUKQ0KIyBzYXZlKGFyYWI0LCBmaWxlID0gImRhdGEvYXJhYjQuUmRhdGEiKQ0KYGBgDQoNCiMgRmlsdGVyIERhdGENCg0KYGBge3J9DQphcmFiNCAlPD4lDQogIGZpbHRlcihxMTAxMiA9PSAxKSAlPiUjb25seSBNdXNsaW1zDQogIG11dGF0ZShzYW1wbGUgPSBpZmVsc2UoaXMubmEoc2FtcGxlKSB8IHNhbXBsZSA9PSAxLCAxLCAyKSkgJT4lIA0KICBmaWx0ZXIoc2FtcGxlICE9IDIpICNvbmx5IG5vbi1yZWZ1Z2Vlcw0KDQphcmFiMyAlPD4lDQogIGZpbHRlcihxMTAxMiA9PSAxKSAjb25seSBNdXNsaW1zDQoNCmFyYWIzDQphcmFiNA0KDQoNCg0KYGBgDQoNCiMgUmVjb2RlIERhdGENCg0KIyMgQXJhYjMNCg0KYGBge3J9DQoNCmFyYWIzICU8PiUgDQogIG11dGF0ZShjbnRyeSA9IHNqbWlzYzo6dG9fbGFiZWwoY291bnRyeSkpICU+JSANCiAgbXV0YXRlKHJlZ2lvbiA9IHNqbWlzYzo6dG9fbGFiZWwoYTEpKSAlPiUgDQogIG11dGF0ZShnb3Zlcm5vcmF0ZSA9IHNqbWlzYzo6dG9fbGFiZWwocTEpKSAlPiUgDQogIG11dGF0ZSh5ZWFyID0gbHVicmlkYXRlOjp5ZWFyKGRhdGUpKQ0KDQogICMgRGVwZW5kZW50IFZhcmlhYmxlDQphcmFiMyAlPD4lIA0KICBtdXRhdGUoaXNsYW1pc3RwYXJ0aWVzMSA9IGlmZWxzZShxNTE4YTIgPiA1LCBOQSwgNSAtIHE1MThhMikpICU+JQ0KICBtdXRhdGUoaXNsYW1pc3RwYXJ0aWVzMiA9IGlmZWxzZShxNTE4YjIgPiA1LCBOQSwgNSAtIHE1MThiMikpICU+JSANCiAgbXV0YXRlKGlzbGFtaXN0cGFydGllcyA9IGNhc2Vfd2hlbigNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMSA9PSAxIH4gMSwNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMSA9PSAyIH4gMiwNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMSA9PSAzIH4gMywNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMSA9PSA0IH4gNCwNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMiA9PSAxIH4gMSwNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMiA9PSAyIH4gMiwNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMiA9PSAzIH4gMywNCiAgICAgICAgaXNsYW1pc3RwYXJ0aWVzMiA9PSA0IH4gNCkNCiAgICApICU+JSAgDQogIG11dGF0ZShpc2xhbWlzdGdvdiA9IGlmZWxzZShxNTE4NCA+IDUsIE5BLCA1IC0gcTUxODQpKSAlPiUgDQogIG11dGF0ZShyZWxpZ2ludGVyZmVyZSA9IGlmZWxzZShxNjA2MSA+IDUsIE5BLCBxNjA2MSkpICU+JSANCiAgbXV0YXRlKHJlbGlnbGVhZGVycyA9IGlmZWxzZShxNjA2MiA+IDUsIE5BLCA1IC0gcTYwNjIpKSAlPiUgDQogIG11dGF0ZShyZWxpZ2xlYWRlcnNpbmZsID0gaWZlbHNlKHE2MDYzID4gNSwgTkEsIDUgLSBxNjA2MykpICU+JQ0KICBtdXRhdGUoc2VwZXJhdGlvbiA9IGlmZWxzZShxNjA2NCA+IDUsIE5BLCBxNjA2NCkpICU+JSANCiAgbXV0YXRlKHJlbGlncGFydHkgPSBSZWNvZGUocTYwNWEsICIxID0gMTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyID0gMTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA0ID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1ID0gMDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDggPSAwOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOSA9IE5BIikpICU+JSANCiAgbXV0YXRlKHJlbGlncGFydHkyID0gUmVjb2RlKHE2MDVhLCAiMSA9IDU7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgPSA0Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAzID0gMjsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNCA9IDE7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDUgPSAzOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDggPSBOQTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA5ID0gTkEiKSkNCg0KaWZlbHNlNGNhdF9yZWMgPC0gZnVuY3Rpb24odmFyaWFibGUpIHsNCiAgcmVjb2RlZCA8LSBpZmVsc2UodmFyaWFibGUgPT0gMCB8IHZhcmlhYmxlID4gNSwgTkEsIDUgLSB2YXJpYWJsZSkNCiAgcmV0dXJuKHJlY29kZWQpDQp9DQoNCg0KYXJhYjMgJTw+JSANCiAgbXV0YXRlKGZlbWFsZSA9IGlmZWxzZShzZXggPT0gMiwgMSwgMCkpICU+JSANCiAgbXV0YXRlKHdvcmsgPSBpZmVsc2UocTEwMDQgPT0gMCB8IHExMDA0ID4gNSwgTkEsIGFicyhxMTAwNCAtIDIpKSkgJT4lIA0KICBtdXRhdGUoaW5jb21lID0gaWZlbHNlNGNhdF9yZWMocTEwMTYpKSAlPiUgDQogIG11dGF0ZShhZ2UgPSBpZmVsc2UocTEwMDEgPT0gMCB8IHExMDAxID09IDk5OTksIE5BLCBxMTAwMSkpICU+JSANCiAgbXV0YXRlKGVkdWMgPSBjYXNlX3doZW4oDQogICAgICAgIHExMDAzID09IDAgfiBOQV9yZWFsXywNCiAgICAgICAgcTEwMDMgPT0gOTkgfiBOQV9yZWFsXywNCiAgICAgICAgcTEwMDMgPT0gNSB+IDQsDQogICAgICAgIHExMDAzID09IDYgfiA1LA0KICAgICAgICBxMTAwMyA9PSA3IH4gNiwNCiAgICAgICAgcTEwMDN5ZW0gPT0gMCB+IE5BX3JlYWxfLA0KICAgICAgICBxMTAwM3llbSA9PSA5OSB+IE5BX3JlYWxfLA0KICAgICAgICBxMTAwM3llbSA9PSA0IH4gMywNCiAgICAgICAgcTEwMDN5ZW0gPT0gNSB+IDQsDQogICAgICAgIHExMDAzeWVtID09IDYgfiA1LA0KICAgICAgICBxMTAwM3llbSA9PSA3IH4gNSwNCiAgICAgICAgcTEwMDN5ZW0gPT0gOCB+IDYsDQogICAgICAgIHExMDAzdCA9PSAwIH4gTkFfcmVhbF8sDQogICAgICAgIHExMDAzdCA9PSA5OSB+IE5BX3JlYWxfLA0KICAgICAgICBxMTAwM3QgPT0gMSB+IDEsDQogICAgICAgIHExMDAzdCA9PSAyIH4gMiwNCiAgICAgICAgcTEwMDN0ID09IDMgfiAzLA0KICAgICAgICBxMTAwM3QgPT0gNCB+IDQsDQogICAgICAgIHExMDAzdCA9PSA1IH4gNSwNCiAgICAgICAgcTEwMDN0ID09IDYgfiA2LA0KICAgIFRSVUUgfiBhcy5udW1lcmljKHExMDAzKSkNCiAgICApICU+JSANCiAgbXV0YXRlKGluZl91cyA9IGlmZWxzZShxNzAxMSA9PSAwIHwgcTcwMTEgPiA1LCBOQSwgcTcwMTEpKSAlPiUgDQogIG11dGF0ZShpbmZfZXUgPSBpZmVsc2UocTcwMTIgPT0gMCB8IHE3MDEyID4gNSwgTkEsIHE3MDEyKSkgJT4lIA0KICBtdXRhdGUoZ2xvYmFsaXNtID0gaWZlbHNlKHE3MDFiID09IDAgfCBxNzAxYiA+IDUsIE5BLCBxNzAxYikpICU+JSANCiAgbXV0YXRlKHByYXkgPSBpZmVsc2UocTYxMDEgPT0gMCB8IHE2MTAxID4gNSwgTkEsIDYgLSBxNjEwMSkpICU+JSANCiAgbXV0YXRlKHF1cmFuID0gaWZlbHNlKHE2MTA2ID09IDAgfCBxNjEwNiA+IDUsIE5BLCA2IC0gcTYxMDYpKSAlPiUNCiAgbXV0YXRlKHdvbWFud29yayA9IGlmZWxzZShxNjAxMiA9PSAwIHwgcTYwMTIgPiA1LCBOQSwgcTYwMTIpKSAlPiUgDQogIG11dGF0ZSh3b21lbmxlYWRlciA9IGlmZWxzZTRjYXRfcmVjKHE2MDEzKSkgJT4lIA0KICBtdXRhdGUod29tZW5lZHVjID0gaWZlbHNlNGNhdF9yZWMocTYwMTQpKSAlPiUgDQogIG11dGF0ZShub2RlbW9jID0gaWZlbHNlKHE2MDcxID09IDAgfCBxNjA3MSA+IDUsIE5BLCBxNjA3MSkpICU+JSANCiAgbXV0YXRlKGdlbmRlcmFwYXJ0dW5pID0gaWZlbHNlNGNhdF9yZWMocTYwNzQpKSAlPiUgDQogIG11dGF0ZShjb3ZlcnVwID0gaWZlbHNlNGNhdF9yZWMocTYwNzYpKSAlPiUgDQogIHNlbGVjdChjbnRyeSwgeWVhciwgcmVnaW9uLCBnb3Zlcm5vcmF0ZSwgaXNsYW1pc3RwYXJ0aWVzICwgaXNsYW1pc3Rnb3YsIHJlbGlnaW50ZXJmZXJlLCByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwsIHNlcGVyYXRpb24sIHJlbGlncGFydHksIHJlbGlncGFydHkyLCBmZW1hbGUsIHdvcmssIGluY29tZSwgIGFnZSwgZWR1YywgZ2xvYmFsaXNtLCBwcmF5LCBxdXJhbiwgd29tYW53b3JrLCB3b21lbmxlYWRlciwgd29tZW5lZHVjLCBub2RlbW9jLCBnZW5kZXJhcGFydHVuaSwgY292ZXJ1cCwgaW5mX3VzLCBpbmZfZXUsIHd0KQ0KDQoNCg0KDQoNCmBgYA0KDQojIyBBcmFiNA0KDQpgYGB7cn0NCnRhYmxlKGFyYWI0JGNvdW50cnkpDQoNCmFyYWI0ICU8PiUgDQogIG11dGF0ZShjbnRyeSA9IHNqbWlzYzo6dG9fbGFiZWwoY291bnRyeSkpICU+JSANCiAgbXV0YXRlKHJlZ2lvbiA9IHNqbWlzYzo6dG9fbGFiZWwoYTEpKSAlPiUgDQogIG11dGF0ZShnb3Zlcm5vcmF0ZSA9IHNqbWlzYzo6dG9fbGFiZWwocTEpKSAlPiUgDQogIG11dGF0ZSh5ZWFyID0gMjAxNikjJT4lDQojICBtdXRhdGUoZGlzdHJpY3QgPSBzam1pc2M6OnRvX2xhYmVsKHEyKSkgDQoNCiMgRGVwZW5kZW50IFZhcmlhYmxlDQphcmFiNCAlPD4lIA0KICBtdXRhdGUoaXNsYW1pc3RwYXJ0aWVzID0gaWZlbHNlKHE1MTgyID4gNSwgTkEsIDUgLSBxNTE4MikpICU+JSANCiAgbXV0YXRlKGlzbGFtaXN0Z292ID0gaWZlbHNlKHE1MTg0ID4gNSwgTkEsIDUgLSBxNTE4NCkpICU+JSANCiAgbXV0YXRlKHJlbGlnaW50ZXJmZXJlID0gaWZlbHNlKHE2MDYxID4gNSwgTkEsIHE2MDYxKSkgJT4lIA0KICBtdXRhdGUocmVsaWdsZWFkZXJzID0gaWZlbHNlKHE2MDYyID4gNSwgTkEsIDUgLSBxNjA2MikpICU+JSANCiAgbXV0YXRlKHJlbGlnbGVhZGVyc2luZmwgPSBpZmVsc2UocTYwNjMgPiA1LCBOQSwgNSAtIHE2MDYzKSkgJT4lDQogIG11dGF0ZShzZXBlcmF0aW9uID0gaWZlbHNlKHE2MDY0ID4gNSwgTkEsIHE2MDY0KSkgJT4lIA0KICBtdXRhdGUocmVsaWdwYXJ0eSA9IFJlY29kZShxNjA1YSwgIjEgPSAxOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgPSAxOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDMgPSAwOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQgPSAwOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDUgPSAwOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTggPSAwOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTkgPSBOQSIpKSAlPiUgDQogIG11dGF0ZShyZWxpZ3BhcnR5MiA9IFJlY29kZShxNjA1YSwgIjEgPSA1Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyID0gNDsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMyA9IDI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQgPSAxOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1ID0gMzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA5OCA9IE5BOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDk5ID0gTkEiKSkNCg0KDQoNCmFyYWI0ICU8PiUgDQogIG11dGF0ZShmZW1hbGUgPSBpZmVsc2UocTEwMDIgPT0gMiwgMSwgMCkpICU+JSANCiAgbXV0YXRlKHdvcmsgPSBpZmVsc2UocTEwMDQgPT0gMCB8IHExMDA0ID4gNSwgTkEsIGFicyhxMTAwNCAtIDIpKSkgJT4lIA0KICBtdXRhdGUoaW5jb21lID0gaWZlbHNlNGNhdF9yZWMocTEwMTYpKSAlPiUgDQogIG11dGF0ZShhZ2UgPSBpZmVsc2UocTEwMDEgPT0gMCB8IHExMDAxID09IDk5OTksIE5BLCBxMTAwMSkpICU+JSANCiAgbXV0YXRlKGVkdWMgPSBjYXNlX3doZW4oDQogICAgICAgIHExMDAzID09IDAgfiBOQV9yZWFsXywNCiAgICAgICAgcTEwMDMgPT0gOTggfiBOQV9yZWFsXywNCiAgICAgICAgcTEwMDMgPT0gOTkgfiBOQV9yZWFsXywNCiAgICAgICAgcTEwMDMgPT0gNSB+IDQsDQogICAgICAgIHExMDAzID09IDYgfiA1LA0KICAgICAgICBxMTAwMyA9PSA3IH4gNiwNCiAgICAgICAgdDEwMDMgPT0gMCB+IE5BX3JlYWxfLA0KICAgICAgICB0MTAwMyA9PSA5OCB+IE5BX3JlYWxfLA0KICAgICAgICB0MTAwMyA9PSA5OSB+IE5BX3JlYWxfLA0KICAgICAgICB0MTAwMyA9PSAzIH4gMywNCiAgICAgICAgdDEwMDMgPT0gNCB+IDQsDQogICAgICAgIHQxMDAzID09IDUgfiA1LA0KICAgICAgICB0MTAwMyA9PSA2IH4gNiwNCiAgICBUUlVFIH4gYXMubnVtZXJpYyhxMTAwMykpDQogICAgKSAlPiUgDQogIG11dGF0ZShpbmZfdXMgPSBpZmVsc2UocTcwMTEgPT0gMCB8IHE3MDExID4gNSwgTkEsIHE3MDExKSkgJT4lIA0KICBtdXRhdGUoaW5mX2V1ID0gaWZlbHNlKHE3MDEyID09IDAgfCBxNzAxMiA+IDUsIE5BLCBxNzAxMikpICU+JSANCiAgbXV0YXRlKGdsb2JhbGlzbSA9IGlmZWxzZShxNzAxYiA9PSAwIHwgcTcwMWIgPiA1LCBOQSwgcTcwMWIpKSAlPiUgDQogIG11dGF0ZShwcmF5ID0gaWZlbHNlKHE2MTAxID09IDAgfCBxNjEwMSA+IDUsIE5BLCA2IC0gcTYxMDEpKSAlPiUgDQogIG11dGF0ZShxdXJhbiA9IGlmZWxzZShxNjEwNiA9PSAwIHwgcTYxMDYgPiA1LCBOQSwgNiAtIHE2MTA2KSkgJT4lIA0KICBtdXRhdGUod29tYW53b3JrID0gaWZlbHNlKHE2MDEyID09IDAgfCBxNjAxMiA+IDUsIE5BLCBxNjAxMikpICU+JSANCiAgbXV0YXRlKHdvbWVubGVhZGVyID0gaWZlbHNlNGNhdF9yZWMocTYwMTMpKSAlPiUgDQogIG11dGF0ZSh3b21lbmVkdWMgPSBpZmVsc2U0Y2F0X3JlYyhxNjAxNCkpICU+JSANCiAgbXV0YXRlKG5vZGVtb2MgPSBpZmVsc2UocTYwNzEgPT0gMCB8IHE2MDcxID4gNSwgTkEsIHE2MDcxKSkgJT4lIA0KICBtdXRhdGUoZ2VuZGVyYXBhcnR1bmkgPSBpZmVsc2U0Y2F0X3JlYyhxNjA3NCkpICU+JSANCiAgbXV0YXRlKGNvdmVydXAgPSBpZmVsc2U0Y2F0X3JlYyhxNjA3NikpICU+JSANCiAgc2VsZWN0KGNudHJ5LCB5ZWFyLCByZWdpb24sIGdvdmVybm9yYXRlICwgaXNsYW1pc3RwYXJ0aWVzICwgaXNsYW1pc3Rnb3YsIHJlbGlnaW50ZXJmZXJlLCByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwsIHNlcGVyYXRpb24sIHJlbGlncGFydHksIHJlbGlncGFydHkyLCBmZW1hbGUsIHdvcmssIGluY29tZSwgIGFnZSwgZWR1YywgZ2xvYmFsaXNtLCBwcmF5LCBxdXJhbiwgd29tYW53b3JrLCB3b21lbmxlYWRlciwgd29tZW5lZHVjLCBub2RlbW9jLCBnZW5kZXJhcGFydHVuaSwgY292ZXJ1cCwgaW5mX3VzLCBpbmZfZXUsIHd0KQ0KDQpgYGANCg0KDQojIE1lcmdpbmcNCg0KYGBge3J9DQphcmFiMzthcmFiNA0KDQphcmFiIDwtIHJiaW5kKGFyYWI0LGFyYWIzKQ0KDQphcmFiDQoNCnRhYmxlKGFyYWIkeWVhcikNCnRhYmxlKGFyYWIkY250cnkpDQpgYGANCg0KIyBGYWN0b3IgQW5hbHlzaXMNCg0KYGBge3J9DQojIGYxIDwtIGFyYWIgJT4lIA0KIyAgIHNlbGVjdChpc2xhbWlzdHBhcnRpZXMsIGlzbGFtaXN0Z292LCANCiMgICAgICAgICAgcmVsaWdsZWFkZXJzLCByZWxpZ2xlYWRlcnNpbmZsKSAlPiUNCiMgICAjIG5hLm9taXQoKSAlPiUgDQojICAgcHN5Y2g6OmZhKDEsIHJvdGF0ZSA9ICJ2YXJpbWF4IiwgICANCiMgICAgICAgICBmbSA9ICJwYSIsDQojICAgICAgICAgc2NvcmVzID0gInJlZ3Jlc3Npb24iLA0KIyAgICAgICAgIHdlaWdodCA9IG5hLm9taXQoYXJhYiR3dCkgICkgICAgICAgICANCiMgZmEuZGlhZ3JhbShmMSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQojIGYxICAgICAgICAgICAgICANCg0KZjIgPC0gYXJhYiAlPiUgDQogIHNlbGVjdChpc2xhbWlzdHBhcnRpZXMsIGlzbGFtaXN0Z292LCANCiAgICAgICAgIHJlbGlnbGVhZGVycywgcmVsaWdsZWFkZXJzaW5mbCkgJT4lIA0KICBwc3ljaDo6cGNhKHdlaWdodCA9IGFyYWIkd3QpIA0KDQphcmFiICU+JSANCiAgc2VsZWN0KGlzbGFtaXN0cGFydGllcywgaXNsYW1pc3Rnb3YsIA0KICAgICAgICAgcmVsaWdsZWFkZXJzLCByZWxpZ2xlYWRlcnNpbmZsKSAlPiUgDQogIGFscGhhKCkgDQoNCmFyYWIgJT4lIA0KICBzZWxlY3QoaXNsYW1pc3RwYXJ0aWVzLCBpc2xhbWlzdGdvdiwgDQogICAgICAgICByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwpICU+JSANCiAgS01PKCkgDQoNCg0KYXJhYjQgJT4lIA0KICBzZWxlY3QoaXNsYW1pc3RwYXJ0aWVzLCBpc2xhbWlzdGdvdiwgDQogICAgICAgICByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwsDQogICAgICAgICByZWxpZ3BhcnR5Miwgc2VwZXJhdGlvbiwNCiAgICAgICAgIHJlbGlnaW50ZXJmZXJlKSAlPiUgDQogIG5hLm9taXQoKSAlPiUgDQogIGNvcigpICANCg0KIyBhcmFiIDwtIHByZWRpY3QucHN5Y2goZjEsIGFyYWIgJT4lIA0KIyAgIHNlbGVjdChpc2xhbWlzdHBhcnRpZXMsIGlzbGFtaXN0Z292LCANCiMgICAgICAgICAgcmVsaWdsZWFkZXJzLCByZWxpZ2xlYWRlcnNpbmZsKSkgJT4lIA0KIyAgIHRibF9kZigpICU+JSANCiMgICBjYmluZChhcmFiKSAlPiUgDQojICAgbXV0YXRlKGlzbGFtaXNtX2ZhID0gUEExKQ0KDQphcmFiIDwtIHByZWRpY3QucHN5Y2goZjIsIGFyYWIgJT4lIA0KICBzZWxlY3QoaXNsYW1pc3RwYXJ0aWVzLCBpc2xhbWlzdGdvdiwgDQogICAgICAgICByZWxpZ2xlYWRlcnMsIHJlbGlnbGVhZGVyc2luZmwpKSAlPiUgDQogIHRibF9kZigpICU+JSANCiAgdHJhbnNtdXRlKGlzbGFtaXNtID0gUEMxKSAlPiUgDQogIGNiaW5kKGFyYWIpIA0KDQojJT4lIA0KIyAgZ2dwbG90KGFlcyhpc2xhbWlzbSkpICsNCiMgIGdlb21faGlzdG9ncmFtKCkgKw0KIyAgZmFjZXRfd3JhcCh+Y250cnksIHNjYWxlcyA9ICJmcmVlIikNCg0KI3NqUGxvdDo6dmlld19kZihhcmFiLCBzaG93LmZycSA9IFQsIHNob3cucHJjID0gVCkNCiMgDQojIGNvci50ZXN0KGFyYWIkUEMxLCBhcmFiJFBBMSkNCg0KYGBgDQoNCiMgQ3JlYXRpbmcgaW5kaWNlcw0KDQpgYGB7cn0NCmYxIDwtIGFyYWIgJT4lIA0KICBzZWxlY3Qod29tYW53b3JrLCB3b21lbmxlYWRlciwgd29tZW5lZHVjKSAlPiUgDQogIGZhKDEsIHJvdGF0ZSA9ICJwcm9tYXgiLCAgIA0KICAgICAgICBmbSA9ICJwYSIsDQogICAgICAgIHNjb3JlcyA9ICJyZWdyZXNzaW9uIikgICAgICAgICAgIA0KZmEuZGlhZ3JhbShmMSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpmMSAgICAgICAgDQoNCmFyYWIgJT4lIA0KICBzZWxlY3Qod29tYW53b3JrLCB3b21lbmxlYWRlciwgd29tZW5lZHVjKSAlPiUgDQogIHBzeWNoOjpwY2EoKSANCg0KZjIgPC0gYXJhYiAlPiUgDQogIHNlbGVjdChwcmF5LCBxdXJhbikgJT4lIA0KICBmYSgxLCByb3RhdGUgPSAicHJvbWF4IiwgICANCiAgICAgICAgZm0gPSAicGEiLA0KICAgICAgICBzY29yZXMgPSAicmVncmVzc2lvbiIpICAgICAgICAgICANCmZhLmRpYWdyYW0oZjIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KZjIgICAgDQoNCmYzIDwtIGFyYWIgJT4lIA0KICBzZWxlY3Qobm9kZW1vYywgZ2VuZGVyYXBhcnR1bmksIGNvdmVydXApICU+JSANCiAgZmEoMSwgcm90YXRlID0gInByb21heCIsICAgDQogICAgICAgIGZtID0gInBhIiwNCiAgICAgICAgc2NvcmVzID0gInJlZ3Jlc3Npb24iKSAgICAgICAgICAgDQpmYS5kaWFncmFtKGYzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmYzICAgIA0KDQphcmFiICU+JSANCiAgc2VsZWN0KG5vZGVtb2MsIGdlbmRlcmFwYXJ0dW5pLCBjb3ZlcnVwKSAlPiUgDQogIEtNTygpDQoNCmFyYWIgJT4lIA0KICBzZWxlY3Qobm9kZW1vYywgZ2VuZGVyYXBhcnR1bmksIGNvdmVydXApICU+JSANCiAgcHN5Y2g6OnBjYSgpDQoNCmFyYWIgJT4lIA0KICBzZWxlY3QoaW5mX2V1LCBpbmZfdXMpICU+JSANCiAgcHN5Y2g6OnBjYSgpDQoNCg0KcmFuZ2UwMSA8LSBmdW5jdGlvbih4KXsoeCAtIG1pbih4LCBuYS5ybSA9IFQpKSAvIChtYXgoeCwgbmEucm0gPSBUKSAtIG1pbih4LCBuYS5ybSA9IFQpKX0NCg0KDQphcmFiX3JlZyA8LSBhcmFiICU+JSANCiAgbXV0YXRlKHBhdHJpYXJjaGFsdmFsdWVzID0gcmFuZ2UwMSh3b21hbndvcmsgKyB3b21lbmxlYWRlciArIHdvbWVuZWR1YykpICAlPiUgDQogIG11dGF0ZShwZXJzb25hbHBpZXR5ID0gcmFuZ2UwMShwcmF5ICsgcXVyYW4pKSAlPiUgDQogIG11dGF0ZShhbnRpd2VzdGVybiA9IHJhbmdlMDEoaW5mX2V1ICsgaW5mX3VzKSkgJT4lIA0KICBtdXRhdGUoaXNsYW1pc20gPSByYW5nZTAxKGlzbGFtaXNtKSAqIDEwMCkgJT4lIA0KICBtdXRhdGVfYXQodmFycyhpc2xhbWlzdHBhcnRpZXM6aW5mX2V1KSwgcmFuZ2UwMSkgJT4lIA0KIyAgbXV0YXRlKGlzbGFtaXNtID0gc2NhbGUoaXNsYW1pc20pKSAlPiUgDQojICBtdXRhdGUoaXNsYW1pc20gPSBzY2FsZShpc2xhbWlzbSkpICU+JSANCiMgIG11dGF0ZV9pZigucHJlZGljYXRlID0gaXMuZG91YmxlLCBzY2FsZSkgDQogIG11dGF0ZShsaWJlcmFsaXNsYW0gPSByYW5nZTAxKG5vZGVtb2MgKyBnZW5kZXJhcGFydHVuaSArIGNvdmVydXApKSAlPiUgDQogIG11dGF0ZShjbnRyeWVhcnMgPSBwYXN0ZShjbnRyeSwgeWVhcikpICU+JSANCiAgbXV0YXRlKHllYXJfMjAxNiA9IGlmZWxzZSh5ZWFyID09IDIwMTYsIDEsIDApKSAlPiUgDQogIG11dGF0ZSh5ZWFyXzIwMTQgPSBpZmVsc2UoeWVhciA9PSAyMDE0LCAxLCAwKSkgJT4lIA0KICBtdXRhdGUoeWVhcl8yMDEzID0gaWZlbHNlKHllYXIgPT0gMjAxMywgMSwgMCkpICU+JSANCiAgbXV0YXRlKHllYXJfMjAxMiA9IGlmZWxzZSh5ZWFyID09IDIwMTIsIDEsIDApKSANCg0KIyBhcmFiX3JlZyRpc2xhbWlzbV9mYSA8LSBhcy5udW1lcmljKHJhbmdlMDEoYXJhYl9yZWckaXNsYW1pc21fZmEpICogMTAwKQ0KIyBhcmFiX3JlZyRpc2xhbWlzbV9wY2EgPC0gYXMubnVtZXJpYyhyYW5nZTAxKGFyYWJfcmVnJGlzbGFtaXNtX3BjYSkgKiAxMDApDQojIA0KIyBhcmFiX3JlZyRpbmNvbWUgICAgICAgICAgICAgPC0gYXMubnVtZXJpYyhzY2FsZShhcmFiX3JlZyRpbmNvbWUpKQ0KIyBhcmFiX3JlZyRhZ2UgICAgICAgICAgICAgICAgPC0gYXMubnVtZXJpYyhzY2FsZShhcmFiX3JlZyRhZ2UpKQ0KIyBhcmFiX3JlZyRlZHVjICAgICAgICAgICAgICAgPC0gYXMubnVtZXJpYyhzY2FsZShhcmFiX3JlZyRlZHVjKSkgDQojIGFyYWJfcmVnJGdsb2JhbGlzbSAgICAgICAgICA8LSBhcy5udW1lcmljKHNjYWxlKGFyYWJfcmVnJGdsb2JhbGlzbSkpICAgDQojIGFyYWJfcmVnJHBlcnNvbmFscGlldHkgICAgICA8LSBhcy5udW1lcmljKHNjYWxlKGFyYWJfcmVnJHBlcnNvbmFscGlldHkpKSAgICAgICANCiMgYXJhYl9yZWckcGF0cmlhcmNoYWx2YWx1ZXMgIDwtIGFzLm51bWVyaWMoc2NhbGUoYXJhYl9yZWckcGF0cmlhcmNoYWx2YWx1ZXMpKSAgICAgICAgICAgDQojIGFyYWJfcmVnJGxpYmVyYWxpc2xhbSAgICAgICA8LSBhcy5udW1lcmljKHNjYWxlKGFyYWJfcmVnJGxpYmVyYWxpc2xhbSkpICAgICANCiMgDQojIGhpc3QoYXJhYl9yZWckbGliZXJhbGlzbGFtKQ0KIyANCiMgDQojIGFyYWJfcmVnICU+JSANCiMgICBzZWxlY3QoaXNsYW1pc21fcGNhICwgZmVtYWxlICwgd29yayAsIGluY29tZSAsIGFnZSAsIGVkdWMgLCBnbG9iYWxpc20gLCBwZXJzb25hbHBpZXR5ICwgcGF0cmlhcmNoYWx2YWx1ZXMgLCBsaWJlcmFsaXNsYW0sIGNudHJ5KSAlPiUgDQojICAgZGVzY3IoKQ0KIyAgIG5hLm9taXQoKSAlPiUgDQojICAgc2VsZWN0KGNudHJ5KSAlPiUgDQojICAgdGFibGUoKQ0KDQp0YWJsZShhcmFiJHllYXIsIGFyYWIkY250cnkpDQoNCnNhdmUoYXJhYl9yZWcsIGZpbGUgPSAiZGF0YS9hcmFiX3JlZy5SZGF0YSIpDQpgYGANCg0KDQojIFJlZ3Jlc3Npb24NCg0KYGBge3J9DQptb2RlbDAgPC0gYXJhYl9yZWcgJT4lIA0KICBsbWU0OjpsbWVyKGlzbGFtaXNtIH4gMSArICgxfGNudHJ5KSwgZGF0YSA9IC4pDQoNCmljYyhtb2RlbDApDQoNCm1vZGVsMWEgPC0gbG1lNDo6bG1lcihpc2xhbWlzbV9wY2EgfiBmZW1hbGUgKyB3b3JrICsgaW5jb21lICsgYWdlICsgZWR1YyArIGdsb2JhbGlzbSArIHBlcnNvbmFscGlldHkgKyBwYXRyaWFyY2hhbHZhbHVlcyArIG5vZGVtb2MgKyBnZW5kZXJhcGFydHVuaSArIGNvdmVydXAgKyAoMXxjbnRyeSksIGRhdGEgPSBhcmFiX3JlZykNCg0KbW9kZWwxIDwtIGxtZTQ6OmxtZXIoaXNsYW1pc20gfiBmZW1hbGUgKyB3b3JrICsgaW5jb21lICsgYWdlICsgZWR1YyArIGdsb2JhbGlzbSArIGFudGl3ZXN0ZXJuICsgcGVyc29uYWxwaWV0eSArIHBhdHJpYXJjaGFsdmFsdWVzICsgbGliZXJhbGlzbGFtICsgeWVhcl8yMDEyICsgeWVhcl8yMDEzICsgeWVhcl8yMDE0ICsgKDF8Y250cnkpLCBkYXRhID0gYXJhYl9yZWcsIHdlaWdodHMgPSB3dCkNCg0KdGV4cmVnOjpzY3JlZW5yZWcobW9kZWwxKQ0KDQphbm92YShtb2RlbDFhLCBtb2RlbDFiKQ0KDQpyLnNxdWFyZWRHTE1NKG1vZGVsMWEpDQoNCnBsb3RfbW9kZWwobW9kZWwxLCB0eXBlID0gInJlIiwgc29ydC5lc3QgPSBULCBzaG93LnZhbHVlcyA9IFQsIHNob3cucCA9IFQsIHZhbHVlLm9mZnNldCA9IDAuNSkNCg0KI3Bsb3RfbW9kZWwobW9kZWwxLCB0eXBlID0gInN0ZCIsIHNvcnQuZXN0ID0gVCwgc2hvdy52YWx1ZXMgPSBULCBzaG93LnAgPSBULCB2YWx1ZS5vZmZzZXQgPSAwLjUpDQoNCnNqcC5sbWVyKG1vZGVsMSwgdHlwZSA9ICJmZS5zdGQiLCBzb3J0LmVzdCA9IFQsIHNob3cudmFsdWVzID0gVCwgc2hvdy5wID0gVCwgeS5vZmZzZXQgPSAwLjQsIHAua3IgPSBGQUxTRSkNCg0KcGxvdF9tb2RlbChtb2RlbDEsIHRlcm1zID0gYygicGVyc29uYWxwaWV0eSIpLCB0eXBlID0gImVmZiIpDQoNCmljYyhtb2RlbDEpDQoNCm1vZGVsMiA8LSBsbWU0OjpsbWVyKGlzbGFtaXNtX3BjYSB+IGZlbWFsZSArIHdvcmsgKyBpbmNvbWUgKyBhZ2UgKyBlZHVjICsgZ2xvYmFsaXNtICsgcGVyc29uYWxwaWV0eSArIHBhdHJpYXJjaGFsdmFsdWVzICsgbGliZXJhbGlzbGFtICsgbGliZXJhbGlzbGFtKnBlcnNvbmFscGlldHkgKyAoMXxjbnRyeS95ZWFyKSwgZGF0YSA9IGFyYWJfcmVnKQ0KDQp0ZXhyZWc6OnNjcmVlbnJlZyhtb2RlbDIpDQoNCg0KcGxvdF9tb2RlbChtb2RlbDIsIHNvcnQuZXN0ID0gVCwgc2hvdy52YWx1ZXMgPSBULCBzaG93LnAgPSBULCB2YWx1ZS5vZmZzZXQgPSAwLjUpDQoNCnNqcC5pbnQobW9kZWwyLCBwLmtyID0gRkFMU0UsIG1kcnQudmFsdWVzID0gImFsbCIpDQoNCnNqcC5sbWVyKG1vZGVsMiwgdHlwZSA9ICJmZS5zdGQiLCBzb3J0LmVzdCA9IFQsIHNob3cudmFsdWVzID0gVCwgc2hvdy5wID0gVCwgeS5vZmZzZXQgPSAwLjQsIHAua3IgPSBGQUxTRSkNCg0KDQojcGxvdF9tb2RlbChtb2RlbDIsIHR5cGUgPSAiaW50IikNCg0KdmlmLm1lciA8LSBmdW5jdGlvbiAoZml0KSB7DQogICMjIGFkYXB0ZWQgZnJvbSBybXM6OnZpZg0KICANCiAgdiA8LSB2Y292KGZpdCkNCiAgbmFtIDwtIG5hbWVzKGZpeGVmKGZpdCkpDQogIA0KICAjIyBleGNsdWRlIGludGVyY2VwdHMNCiAgbnMgPC0gc3VtKDEgKiAobmFtID09ICJJbnRlcmNlcHQiIHwgbmFtID09ICIoSW50ZXJjZXB0KSIpKQ0KICBpZiAobnMgPiAwKSB7DQogICAgdiA8LSB2Wy0oMTpucyksIC0oMTpucyksIGRyb3AgPSBGQUxTRV0NCiAgICBuYW0gPC0gbmFtWy0oMTpucyldDQogIH0NCiAgDQogIGQgPC0gZGlhZyh2KV4wLjUNCiAgdiA8LSBkaWFnKHNvbHZlKHYvKGQgJW8lIGQpKSkNCiAgbmFtZXModikgPC0gbmFtDQogIHYNCn0NCg0KdmlmLm1lcihtb2RlbDIpDQoNCg0KDQptb2RlbDMgPC0gbG1lNDo6bG1lcihpc2xhbWlzbV9wY2EgfiBmZW1hbGUgKyB3b3JrICsgaW5jb21lICsgYWdlICsgZWR1YyArIGdsb2JhbGlzbSArIHBlcnNvbmFscGlldHkgKyBwYXRyaWFyY2hhbHZhbHVlcyArIG5vZGVtb2MgKyBnZW5kZXJhcGFydHVuaSArIGNvdmVydXAgKyBwYXRyaWFyY2hhbHZhbHVlcypwZXJzb25hbHBpZXR5ICsgKDF8Y250cnkveWVhciksIGRhdGEgPSBhcmFiX3JlZykNCg0KdGV4cmVnOjpzY3JlZW5yZWcobW9kZWwzKQ0KDQoNCnBsb3RfbW9kZWwobW9kZWwzLCBzb3J0LmVzdCA9IFQsIHNob3cudmFsdWVzID0gVCwgc2hvdy5wID0gVCwgdmFsdWUub2Zmc2V0ID0gMC41KQ0KDQpzanAuaW50KG1vZGVsMywgcC5rciA9IEZBTFNFLCBtZHJ0LnZhbHVlcyA9ICJhbGwiKQ0KDQpzanAubG1lcihtb2RlbDMsIHR5cGUgPSAiZmUuc3RkIiwgc29ydC5lc3QgPSBULCBzaG93LnZhbHVlcyA9IFQsIHNob3cucCA9IFQsIHkub2Zmc2V0ID0gMC40LCBwLmtyID0gRkFMU0UpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KbW9kZWwxIDwtIGFyYWJfcmVnICU+JSANCiAgbG1lNDo6bG1lcihpc2xhbWlzbSB+IGZlbWFsZSArIHdvcmsgKyBpbmNvbWUgKyBhZ2UgKyBlZHVjICsgZ2xvYmFsaXNtICsgcHJheSArIHF1cmFuICsgd29tYW53b3JrICsgd29tZW5sZWFkZXIgKyB3b21lbmVkdWMgKyBub2RlbW9jICsgZ2VuZGVyYXBhcnR1bmkgKyBjb3ZlcnVwICsgKDF8Y250cnkveWVhciksIGRhdGEgPSAuKQ0KDQp0ZXhyZWc6OnNjcmVlbnJlZyhtb2RlbDEpDQoNCnBsb3RfbW9kZWwobW9kZWwxLCBzb3J0LmVzdCA9IFQsIHNob3cudmFsdWVzID0gVCwgc2hvdy5wID0gVCwgdmFsdWUub2Zmc2V0ID0gMC41KQ0KDQoNCnBsb3RfbW9kZWwobW9kZWwxLCB0ZXJtcyA9IGMoIm5vZGVtb2MiLCAiZmVtYWxlIiksIHR5cGUgPSAicHJlZCIpDQoNCm1vZGVsMiA8LSBhcmFiX3JlZyAlPiUgDQogIGxtZTQ6OmxtZXIoaXNsYW1pc20gfiBmZW1hbGUgKyB3b3JrICsgaW5jb21lICsgYWdlICsgZWR1YyArIGdsb2JhbGlzbSArIHByYXkgKyBxdXJhbiArIHdvbWFud29yayArIHdvbWVubGVhZGVyICsgd29tZW5lZHVjICsgbm9kZW1vYyArIGdlbmRlcmFwYXJ0dW5pICsgY292ZXJ1cCArIG5vZGVtb2MqcXVyYW4gKyAoMXxjbnRyeS95ZWFyKSwgZGF0YSA9IC4pDQoNCnRleHJlZzo6c2NyZWVucmVnKG1vZGVsMikNCmBgYA0KDQoNCmBgYHtyfQ0Kdmlld19kZjIgPC0gZnVuY3Rpb24gKHgsIHdlaWdodC5ieSA9IE5VTEwsIGFsdHIucm93LmNvbCA9IFRSVUUsIHNob3cuaWQgPSBUUlVFLCANCiAgc2hvdy50eXBlID0gRkFMU0UsIHNob3cudmFsdWVzID0gVFJVRSwgc2hvdy5zdHJpbmcudmFsdWVzID0gRkFMU0UsIA0KICBzaG93LmxhYmVscyA9IFRSVUUsIHNob3cuZnJxID0gRkFMU0UsIHNob3cucHJjID0gRkFMU0UsIA0KICBzaG93Lnd0ZC5mcnEgPSBGQUxTRSwgc2hvdy53dGQucHJjID0gRkFMU0UsIHNob3cubmEgPSBGQUxTRSwgDQogIG1heC5sZW4gPSAxNSwgc29ydC5ieS5uYW1lID0gRkFMU0UsIHdyYXAubGFiZWxzID0gNTAsIGhpZGUucHJvZ3Jlc3MgPSBGQUxTRSwgDQogIENTUyA9IE5VTEwsIGVuY29kaW5nID0gTlVMTCwgZmlsZSA9IE5VTEwsIHVzZS52aWV3ZXIgPSBUUlVFLCANCiAgbm8ub3V0cHV0ID0gRkFMU0UsIHJlbW92ZS5zcGFjZXMgPSBUUlVFKSANCnsNCiAgZ2V0LmVuY29kaW5nIDwtIGZ1bmN0aW9uKGVuY29kaW5nLCBkYXRhID0gTlVMTCkgew0KICBpZiAoaXMubnVsbChlbmNvZGluZykpIHsNCiAgICBpZiAoIWlzLm51bGwoZGF0YSkgJiYgaXMuZGF0YS5mcmFtZShkYXRhKSkgew0KICAgICAgIyBnZXQgdmFyaWFibGUgbGFiZWwNCiAgICAgIGxhYnMgPC0gc2psYWJlbGxlZDo6Z2V0X2xhYmVsKGRhdGFbWzFdXSkNCiAgICAgICMgY2hlY2sgaWYgdmVjdG9ycyBvZiBkYXRhIGZyYW1lIGhhdmUNCiAgICAgICMgYW55IHZhbGlkIGxhYmVsLiBlbHNlLCBkZWZhdWx0IHRvIHV0Zi04DQogICAgICBpZiAoIWlzLm51bGwobGFicykgJiYgaXMuY2hhcmFjdGVyKGxhYnMpKQ0KICAgICAgICBlbmNvZGluZyA8LSBFbmNvZGluZyhzamxhYmVsbGVkOjpnZXRfbGFiZWwoZGF0YVtbMV1dKSkNCiAgICAgIGVsc2UNCiAgICAgICAgZW5jb2RpbmcgPC0gIlVURi04Ig0KICAgICAgIyB1bmtub3duIGVuY29kaW5nPyBkZWZhdWx0IHRvIHV0Zi04DQogICAgICBpZiAoZW5jb2RpbmcgPT0gInVua25vd24iKSBlbmNvZGluZyA8LSAiVVRGLTgiDQogICAgfSBlbHNlIGlmICguUGxhdGZvcm0kT1MudHlwZSA9PSAidW5peCIpDQogICAgICBlbmNvZGluZyA8LSAiVVRGLTgiDQogICAgZWxzZQ0KICAgICAgZW5jb2RpbmcgPC0gIldpbmRvd3MtMTI1MiINCiAgfQ0KICByZXR1cm4oZW5jb2RpbmcpDQp9DQoNCiAgaGFzX3ZhbHVlX2xhYmVscyA8LSBmdW5jdGlvbih4KSB7DQogICEoaXMubnVsbChhdHRyKHgsICJsYWJlbHMiLCBleGFjdCA9IFQpKSAmJiBpcy5udWxsKGF0dHIoeCwgInZhbHVlLmxhYmVscyIsIGV4YWN0ID0gVCkpKQ0KfQ0KDQogIHNqdS5ybXNwYyA8LSBmdW5jdGlvbihodG1sLnRhYmxlKSB7DQogIGNsZWFuZWQgPC0gZ3N1YigiICAgICAgPCIsICI8IiwgaHRtbC50YWJsZSwgZml4ZWQgPSBUUlVFLCB1c2VCeXRlcyA9IFRSVUUpDQogIGNsZWFuZWQgPC0gZ3N1YigiICAgIDwiLCAiPCIsIGNsZWFuZWQsIGZpeGVkID0gVFJVRSwgdXNlQnl0ZXMgPSBUUlVFKQ0KICBjbGVhbmVkIDwtIGdzdWIoIiAgPCIsICI8IiwgY2xlYW5lZCwgZml4ZWQgPSBUUlVFLCB1c2VCeXRlcyA9IFRSVUUpDQogIHJldHVybihjbGVhbmVkKQ0KICB9DQogIA0KICBmcnEudmFsdWUgPC0gZnVuY3Rpb24oaW5kZXgsIHgsIGRmLnZhbCwgd2VpZ2h0cyA9IE5VTEwpIHsNCiAgdmFsc3RyaW5nIDwtICIiDQogICMgY2hlY2sgaWYgd2UgaGF2ZSBhIHZhbGlkIGluZGV4DQogIGlmIChpbmRleCA8PSBuY29sKHgpICYmICFpcy5udWxsKGRmLnZhbFtbaW5kZXhdXSkpIHsNCiAgICAjIGRvIHdlIGhhdmUgd2VpZ2h0cz8NCiAgICBpZiAoIWlzLm51bGwod2VpZ2h0cykpDQogICAgICB2YXJpYWIgPC0gc2pzdGF0czo6d2VpZ2h0KHhbW2luZGV4XV0sIHdlaWdodHMpDQogICAgZWxzZQ0KICAgICAgdmFyaWFiIDwtIHhbW2luZGV4XV0NCiAgICAjIGNyZWF0ZSBmcmVxdWVuY3kgdGFibGUuIHNhbWUgZnVuY3Rpb24gYXMgZm9yDQogICAgIyBzanQuZnJxIGFuZCBzanAuZnJxDQogICAgZnRhYiA8LSBjcmVhdGUuZnJxLmRmKHZhcmlhYiwgMjApJG15ZGF0JGZycQ0KICAgICMgcmVtb3ZlIGxhc3QgdmFsdWUsIHdoaWNoIGlzIE4gZm9yIE5BDQogICAgaWYgKGxlbmd0aChmdGFiKSA9PSAxICYmIGlzLm5hKGZ0YWIpKSB7DQogICAgICB2YWxzdHJpbmcgPC0gIjxOQT4iDQogICAgfSBlbHNlIHsNCiAgICAgIGZvciAoaSBpbiAxOihsZW5ndGgoZnRhYikgLSAxKSkgew0KICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgZnRhYltpXSkNCiAgICAgICAgaWYgKGkgPCBsZW5ndGgoZnRhYikpIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCAiPGJyPiIpDQogICAgICB9DQogICAgfQ0KICB9IGVsc2Ugew0KICAgIHZhbHN0cmluZyA8LSAiIg0KICB9DQogIHJldHVybih2YWxzdHJpbmcpDQp9DQoNCnByYy52YWx1ZSA8LSBmdW5jdGlvbihpbmRleCwgeCwgZGYudmFsLCB3ZWlnaHRzID0gTlVMTCkgew0KICB2YWxzdHJpbmcgPC0gIiINCiAgIyBjaGVjayBmb3IgdmFsaWQgaW5kaWNlcw0KICBpZiAoaW5kZXggPD0gbmNvbCh4KSAmJiAhaXMubnVsbChkZi52YWxbW2luZGV4XV0pKSB7DQogICAgIyBkbyB3ZSBoYXZlIHdlaWdodHM/DQogICAgaWYgKCFpcy5udWxsKHdlaWdodHMpKQ0KICAgICAgdmFyaWFiIDwtIHNqc3RhdHM6OndlaWdodCh4W1tpbmRleF1dLCB3ZWlnaHRzKQ0KICAgIGVsc2UNCiAgICAgIHZhcmlhYiA8LSB4W1tpbmRleF1dDQogICAgIyBjcmVhdGUgZnJlcXVlbmN5IHRhYmxlLCBidXQgb25seSBnZXQgdmFsaWQgcGVyY2VudGFnZXMNCiAgICBmdGFiIDwtIGNyZWF0ZS5mcnEuZGYodmFyaWFiLCAyMCkkbXlkYXQkdmFsaWQucHJjDQogICAgIyByZW1vdmUgbGFzdCB2YWx1ZSwgd2hpY2ggaXMgYSBOQSBkdW1teQ0KICAgIGlmIChsZW5ndGgoZnRhYikgPT0gMSAmJiBpcy5uYShmdGFiKSkgew0KICAgICAgdmFsc3RyaW5nIDwtICI8TkE+Ig0KICAgIH0gZWxzZSB7DQogICAgICBmb3IgKGkgaW4gMToobGVuZ3RoKGZ0YWIpIC0gMSkpIHsNCiAgICAgICAgdmFsc3RyaW5nIDwtIHBhc3RlMCh2YWxzdHJpbmcsIHNwcmludGYoIiUuMmYiLCBmdGFiW2ldKSkNCiAgICAgICAgaWYgKGkgPCBsZW5ndGgoZnRhYikpIHZhbHN0cmluZyA8LSBwYXN0ZTAodmFsc3RyaW5nLCAiPGJyPiIpDQogICAgICB9DQogICAgfQ0KICB9IGVsc2Ugew0KICAgIHZhbHN0cmluZyA8LSAiIg0KICB9DQogIHJldHVybih2YWxzdHJpbmcpDQp9DQogIA0KICBlbmNvZGluZyA8LSBnZXQuZW5jb2RpbmcoZW5jb2RpbmcsIHgpDQogIGlmICghaXMuZGF0YS5mcmFtZSh4KSkgDQogICAgc3RvcCgiUGFyYW1ldGVyIG5lZWRzIHRvIGJlIGEgZGF0YSBmcmFtZSEiLCBjYWxsLiA9IEZBTFNFKQ0KICBkZi52YXIgPC0gc2psYWJlbGxlZDo6Z2V0X2xhYmVsKHgpDQogIGRmLnZhbCA8LSBzamxhYmVsbGVkOjpnZXRfbGFiZWxzKHgpDQogIGNvbGNudCA8LSBuY29sKHgpDQogIGlkIDwtIHNlcV9sZW4oY29sY250KQ0KICBpZiAoc29ydC5ieS5uYW1lKSANCiAgICBpZCA8LSBpZFtvcmRlcihjb2xuYW1lcyh4KSldDQogIHRhZy50YWJsZSA8LSAidGFibGUiDQogIHRhZy50aGVhZCA8LSAidGhlYWQiDQogIHRhZy50ZGF0YSA8LSAidGRhdGEiDQogIHRhZy5hcmMgPC0gImFyYyINCiAgdGFnLmNhcHRpb24gPC0gImNhcHRpb24iDQogIHRhZy5vbWl0IDwtICJvbWl0Ig0KICBjc3MudGFibGUgPC0gImJvcmRlci1jb2xsYXBzZTpjb2xsYXBzZTsgYm9yZGVyOm5vbmU7Ig0KICBjc3MudGhlYWQgPC0gImJvcmRlci1ib3R0b206ZG91YmxlOyBmb250LXN0eWxlOml0YWxpYzsgZm9udC13ZWlnaHQ6bm9ybWFsOyBwYWRkaW5nOjAuMmNtOyB0ZXh0LWFsaWduOmxlZnQ7IHZlcnRpY2FsLWFsaWduOnRvcDsiDQogIGNzcy50ZGF0YSA8LSAicGFkZGluZzowLjJjbTsgdGV4dC1hbGlnbjpsZWZ0OyB2ZXJ0aWNhbC1hbGlnbjp0b3A7Ig0KICBjc3MuYXJjIDwtICJiYWNrZ3JvdW5kLWNvbG9yOiNlZWVlZWUiDQogIGNzcy5jYXB0aW9uIDwtICJmb250LXdlaWdodDogYm9sZDsgdGV4dC1hbGlnbjpsZWZ0OyINCiAgY3NzLm9taXQgPC0gImNvbG9yOiM5OTk5OTk7Ig0KICBpZiAoIWlzLm51bGwoQ1NTKSkgew0KICAgIGlmICghaXMubnVsbChDU1NbWyJjc3MudGFibGUiXV0pKSANCiAgICAgIGNzcy50YWJsZSA8LSBpZmVsc2Uoc3Vic3RyaW5nKENTU1tbImNzcy50YWJsZSJdXSwgDQogICAgICAgIDEsIDEpID09ICIrIiwgcGFzdGUwKGNzcy50YWJsZSwgc3Vic3RyaW5nKENTU1tbImNzcy50YWJsZSJdXSwgDQogICAgICAgIDIpKSwgQ1NTW1siY3NzLnRhYmxlIl1dKQ0KICAgIGlmICghaXMubnVsbChDU1NbWyJjc3MudGhlYWQiXV0pKSANCiAgICAgIGNzcy50aGVhZCA8LSBpZmVsc2Uoc3Vic3RyaW5nKENTU1tbImNzcy50aGVhZCJdXSwgDQogICAgICAgIDEsIDEpID09ICIrIiwgcGFzdGUwKGNzcy50aGVhZCwgc3Vic3RyaW5nKENTU1tbImNzcy50aGVhZCJdXSwgDQogICAgICAgIDIpKSwgQ1NTW1siY3NzLnRoZWFkIl1dKQ0KICAgIGlmICghaXMubnVsbChDU1NbWyJjc3MudGRhdGEiXV0pKSANCiAgICAgIGNzcy50ZGF0YSA8LSBpZmVsc2Uoc3Vic3RyaW5nKENTU1tbImNzcy50ZGF0YSJdXSwgDQogICAgICAgIDEsIDEpID09ICIrIiwgcGFzdGUwKGNzcy50ZGF0YSwgc3Vic3RyaW5nKENTU1tbImNzcy50ZGF0YSJdXSwgDQogICAgICAgIDIpKSwgQ1NTW1siY3NzLnRkYXRhIl1dKQ0KICAgIGlmICghaXMubnVsbChDU1NbWyJjc3MuYXJjIl1dKSkgDQogICAgICBjc3MuYXJjIDwtIGlmZWxzZShzdWJzdHJpbmcoQ1NTW1siY3NzLmFyYyJdXSwgMSwgDQogICAgICAgIDEpID09ICIrIiwgcGFzdGUwKGNzcy5hcmMsIHN1YnN0cmluZyhDU1NbWyJjc3MuYXJjIl1dLCANCiAgICAgICAgMikpLCBDU1NbWyJjc3MuYXJjIl1dKQ0KICAgIGlmICghaXMubnVsbChDU1NbWyJjc3MuY2FwdGlvbiJdXSkpIA0KICAgICAgY3NzLmNhcHRpb24gPC0gaWZlbHNlKHN1YnN0cmluZyhDU1NbWyJjc3MuY2FwdGlvbiJdXSwgDQogICAgICAgIDEsIDEpID09ICIrIiwgcGFzdGUwKGNzcy5jYXB0aW9uLCBzdWJzdHJpbmcoQ1NTW1siY3NzLmNhcHRpb24iXV0sIA0KICAgICAgICAyKSksIENTU1tbImNzcy5jYXB0aW9uIl1dKQ0KICAgIGlmICghaXMubnVsbChDU1NbWyJjc3Mub21pdCJdXSkpIA0KICAgICAgY3NzLm9taXQgPC0gaWZlbHNlKHN1YnN0cmluZyhDU1NbWyJjc3Mub21pdCJdXSwgDQogICAgICAgIDEsIDEpID09ICIrIiwgcGFzdGUwKGNzcy5vbWl0LCBzdWJzdHJpbmcoQ1NTW1siY3NzLm9taXQiXV0sIA0KICAgICAgICAyKSksIENTU1tbImNzcy5vbWl0Il1dKQ0KICB9DQogIHBhZ2Uuc3R5bGUgPC0gc3ByaW50ZigiPHN0eWxlPlxuaHRtbCwgYm9keSB7IGJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB9XG4lcyB7ICVzIH1cbi4lcyB7ICVzIH1cbi4lcyB7ICVzIH1cbi4lcyB7ICVzIH1cbiVzIHsgJXMgfVxuLiVzIHsgJXMgfVxuPC9zdHlsZT4iLCANCiAgICB0YWcudGFibGUsIGNzcy50YWJsZSwgdGFnLnRoZWFkLCBjc3MudGhlYWQsIHRhZy50ZGF0YSwgDQogICAgY3NzLnRkYXRhLCB0YWcuYXJjLCBjc3MuYXJjLCB0YWcuY2FwdGlvbiwgY3NzLmNhcHRpb24sIA0KICAgIHRhZy5vbWl0LCBjc3Mub21pdCkNCiAgdG9Xcml0ZSA8LSBzcHJpbnRmKCI8aHRtbD5cbjxoZWFkPlxuPG1ldGEgaHR0cC1lcXVpdj1cIkNvbnRlbnQtdHlwZVwiIGNvbnRlbnQ9XCJ0ZXh0L2h0bWw7Y2hhcnNldD0lc1wiPlxuJXNcbjwvaGVhZD5cbjxib2R5PlxuIiwgDQogICAgZW5jb2RpbmcsIHBhZ2Uuc3R5bGUpDQogIHBhZ2UuY29udGVudCA8LSBzcHJpbnRmKCI8dGFibGU+XG4gIDxjYXB0aW9uPkRhdGEgZnJhbWU6ICVzPC9jYXB0aW9uPlxuIiwgDQogICAgZGVwYXJzZShzdWJzdGl0dXRlKHgpKSkNCiAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICIgIDx0cj5cbiAgICAiKQ0KICBpZiAoc2hvdy5pZCkgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPklEPC90aD4iKQ0KICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIjx0aCBjbGFzcz1cInRoZWFkXCI+TmFtZTwvdGg+IikNCiAgaWYgKHNob3cudHlwZSkgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPlR5cGU8L3RoPiIpDQogIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj5MYWJlbDwvdGg+IikNCiAgaWYgKHNob3cubmEpIA0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj5taXNzaW5nczwvdGg+IikNCiAgaWYgKHNob3cudmFsdWVzKSANCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIjx0aCBjbGFzcz1cInRoZWFkXCI+VmFsdWVzPC90aD4iKQ0KICBpZiAoc2hvdy5sYWJlbHMpIA0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj5WYWx1ZSBMYWJlbHM8L3RoPiIpDQogIGlmIChzaG93LmZycSkgDQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsICI8dGggY2xhc3M9XCJ0aGVhZFwiPkZyZXEuPC90aD4iKQ0KICBpZiAoc2hvdy5wcmMpIA0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj4lPC90aD4iKQ0KICBpZiAoc2hvdy53dGQuZnJxKSANCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIjx0aCBjbGFzcz1cInRoZWFkXCI+d2VpZ2h0ZWQgRnJlcS48L3RoPiIpDQogIGlmIChzaG93Lnd0ZC5wcmMpIA0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiPHRoIGNsYXNzPVwidGhlYWRcIj53ZWlnaHRlZCAlPC90aD4iKQ0KICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgIlxuICA8L3RyPlxuIikNCiAgaWYgKCFoaWRlLnByb2dyZXNzKSANCiAgICBwYiA8LSB1dGlsczo6dHh0UHJvZ3Jlc3NCYXIobWluID0gMCwgbWF4ID0gY29sY250LCBzdHlsZSA9IDMpDQogIGZvciAoY2NudCBpbiBzZXFfbGVuKGNvbGNudCkpIHsNCiAgICBpbmRleCA8LSBpZFtjY250XQ0KICAgIGFyY3N0cmluZyA8LSAiIg0KICAgIGlmIChhbHRyLnJvdy5jb2wpIA0KICAgICAgYXJjc3RyaW5nIDwtIGlmZWxzZShzam1pc2M6OmlzX2V2ZW4oY2NudCksICIgYXJjIiwgDQogICAgICAgICIiKQ0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiICA8dHI+XG4iKQ0KICAgIGlmIChzaG93LmlkKSANCiAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVpPC90ZD5cbiIsIA0KICAgICAgICBhcmNzdHJpbmcsIGluZGV4KSkNCiAgICBpZiAoIWlzLmxpc3QoeFtbaW5kZXhdXSkgJiYgIWlzLm51bGwoc2psYWJlbGxlZDo6Z2V0X25vdGUoeFtbaW5kZXhdXSkpKSANCiAgICAgIHRkLnRpdGxlLnRhZyA8LSBzcHJpbnRmKCIgdGl0bGU9XCIlc1wiIiwgc2psYWJlbGxlZDo6Z2V0X25vdGUoeFtbaW5kZXhdXSkpDQogICAgZWxzZSB0ZC50aXRsZS50YWcgPC0gIiINCiAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIiVzPiVzPC90ZD5cbiIsIA0KICAgICAgYXJjc3RyaW5nLCB0ZC50aXRsZS50YWcsIGNvbG5hbWVzKHgpW2luZGV4XSkpDQogICAgaWYgKHNob3cudHlwZSkgew0KICAgICAgdmFydHlwZSA8LSBzam1pc2M6OnZhcl90eXBlKHhbW2luZGV4XV0pDQogICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgICAgYXJjc3RyaW5nLCB2YXJ0eXBlKSkNCiAgICB9DQogICAgaWYgKGluZGV4IDw9IGxlbmd0aChkZi52YXIpKSB7DQogICAgICB2YXJsYWIgPC0gZGYudmFyW2luZGV4XQ0KICAgICAgaWYgKCFpcy5udWxsKHdyYXAubGFiZWxzKSkgew0KICAgICAgICB2YXJsYWIgPC0gc2ptaXNjOjp3b3JkX3dyYXAodmFybGFiLCB3cmFwLmxhYmVscywgDQogICAgICAgICAgIjxicj4iKQ0KICAgICAgfQ0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgIHZhcmxhYiA8LSAiPE5BPiINCiAgICB9DQogICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsIHNwcmludGYoIiAgICA8dGQgY2xhc3M9XCJ0ZGF0YSVzXCI+JXM8L3RkPlxuIiwgDQogICAgICBhcmNzdHJpbmcsIHZhcmxhYikpDQogICAgaWYgKHNob3cubmEpIHsNCiAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSB7DQogICAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDtsaXN0Jmd0Ozwvc3Bhbj48L3RkPlxuIiwgDQogICAgICAgICAgYXJjc3RyaW5nKSkNCiAgICAgIH0NCiAgICAgIGVsc2Ugew0KICAgICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4laSAoJS4yZiUlKTwvdGQ+XG4iLCANCiAgICAgICAgICBhcmNzdHJpbmcsIHN1bShpcy5uYSh4W1tpbmRleF1dKSwgbmEucm0gPSBUKSwgDQogICAgICAgICAgMTAwICogc3VtKGlzLm5hKHhbW2luZGV4XV0pLCBuYS5ybSA9IFQpL25yb3coeCkpKQ0KICAgICAgfQ0KICAgIH0NCiAgICBpZiAoaXMubnVtZXJpYyh4W1tpbmRleF1dKSAmJiAhaGFzX3ZhbHVlX2xhYmVscyh4W1tpbmRleF1dKSkgew0KICAgICAgaWYgKHNob3cudmFsdWVzIHx8IHNob3cubGFiZWxzKSB7DQogICAgICAgIHZhbHN0cmluZyA8LSBwYXN0ZTAoc3ByaW50ZigiJWEiLCByYW5nZSh4W1tpbmRleF1dLCANCiAgICAgICAgICBuYS5ybSA9IFQpKSwgY29sbGFwc2UgPSAiLSIpDQogICAgICAgIGlmIChzaG93LnZhbHVlcyAmJiBzaG93LmxhYmVscykgew0KICAgICAgICAgIGNvbHNwIDwtICIgY29sc3Bhbj1cIjJcIiINCiAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKCI8ZW0+cmFuZ2U6ICIsIHZhbHN0cmluZywgDQogICAgICAgICAgICAiPC9lbT4iKQ0KICAgICAgICB9DQogICAgICAgIGVsc2Ugew0KICAgICAgICAgIGNvbHNwIDwtICIiDQogICAgICAgIH0NCiAgICAgICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsIHNwcmludGYoIiAgICA8dGQgY2xhc3M9XCJ0ZGF0YSVzXCIlcz4lczwvdGQ+XG4iLCANCiAgICAgICAgICBhcmNzdHJpbmcsIGNvbHNwLCB2YWxzdHJpbmcpKQ0KICAgICAgfQ0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgIGlmIChzaG93LnZhbHVlcykgew0KICAgICAgICB2YWxzdHJpbmcgPC0gIiINCiAgICAgICAgaWYgKGluZGV4IDw9IG5jb2woeCkpIHsNCiAgICAgICAgICBpZiAoaXMubGlzdCh4W1tpbmRleF1dKSkgew0KICAgICAgICAgICAgdmFsc3RyaW5nIDwtICI8c3BhbiBjbGFzcz1cIm9taXRcIj4mbHQ7bGlzdCZndDs8L3NwYW4+Ig0KICAgICAgICAgIH0NCiAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgIHZhbHMgPC0gc2psYWJlbGxlZDo6Z2V0X3ZhbHVlcyh4W1tpbmRleF1dKQ0KICAgICAgICAgICAgaWYgKCFpcy5udWxsKHZhbHMpKSB7DQogICAgICAgICAgICAgIGxvb3AgPC0gbmEub21pdChzZXFfbGVuKGxlbmd0aCh2YWxzKSlbMTptYXgubGVuXSkNCiAgICAgICAgICAgICAgZm9yIChpIGluIGxvb3ApIHsNCiAgICAgICAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgdmFsc1tpXSkNCiAgICAgICAgICAgICAgICBpZiAoaSA8IGxlbmd0aCh2YWxzKSkgDQogICAgICAgICAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgIjxicj4iKQ0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIGlmIChtYXgubGVuIDwgbGVuZ3RoKHZhbHMpKSANCiAgICAgICAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDsuLi4mZ3Q7PC9zcGFuPiIpDQogICAgICAgICAgICB9DQogICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIGVsc2Ugew0KICAgICAgICAgIHZhbHN0cmluZyA8LSAiPE5BPiINCiAgICAgICAgfQ0KICAgICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgICAgICBhcmNzdHJpbmcsIHZhbHN0cmluZykpDQogICAgICB9DQogICAgICBpZiAoc2hvdy5sYWJlbHMpIHsNCiAgICAgICAgdmFsc3RyaW5nIDwtICIiDQogICAgICAgIGlmIChpbmRleCA8PSBsZW5ndGgoZGYudmFsKSkgew0KICAgICAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSB7DQogICAgICAgICAgICB2YWxzdHJpbmcgPC0gIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDtsaXN0Jmd0Ozwvc3Bhbj4iDQogICAgICAgICAgfQ0KICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgdmFscyA8LSBkZi52YWxbW2luZGV4XV0NCiAgICAgICAgICAgIGlmICghaXMubnVsbCh2YWxzKSkgDQogICAgICAgICAgICAgIHZhbHMgPC0gbmEub21pdCh2YWxzKQ0KICAgICAgICAgICAgaWYgKGlzLmNoYXJhY3Rlcih4W1tpbmRleF1dKSAmJiAhaXMubnVsbCh2YWxzKSAmJiANCiAgICAgICAgICAgICAgIXNqbWlzYzo6aXNfZW1wdHkodmFscykpIHsNCiAgICAgICAgICAgICAgaWYgKHNob3cuc3RyaW5nLnZhbHVlcykgDQogICAgICAgICAgICAgICAgdmFscyA8LSBzb3J0KHZhbHMpDQogICAgICAgICAgICAgIGVsc2UgdmFscyA8LSAiPHNwYW4gY2xhc3M9XCJvbWl0XCIgdGl0bGUgPVwiJ3Nob3cuc3RyaW5nLnZhbHVlcyA9IFRSVUUnIHRvIHNob3cgdmFsdWVzLlwiPiZsdDtvdXRwdXQgb21pdHRlZCZndDs8L3NwYW4+Ig0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKCFpcy5udWxsKHZhbHMpKSB7DQogICAgICAgICAgICAgIGxvb3AgPC0gbmEub21pdChzZXFfbGVuKGxlbmd0aCh2YWxzKSlbMTptYXgubGVuXSkNCiAgICAgICAgICAgICAgZm9yIChpIGluIGxvb3ApIHsNCiAgICAgICAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgdmFsc1tpXSkNCiAgICAgICAgICAgICAgICBpZiAoaSA8IGxlbmd0aCh2YWxzKSkgDQogICAgICAgICAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgIjxicj4iKQ0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIGlmIChtYXgubGVuIDwgbGVuZ3RoKHZhbHMpKSANCiAgICAgICAgICAgICAgICB2YWxzdHJpbmcgPC0gcGFzdGUwKHZhbHN0cmluZywgIjxzcGFuIGNsYXNzPVwib21pdFwiPiZsdDsuLi4gdHJ1bmNhdGVkJmd0Ozwvc3Bhbj4iKQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBlbHNlIHsNCiAgICAgICAgICB2YWxzdHJpbmcgPC0gIjxOQT4iDQogICAgICAgIH0NCiAgICAgICAgcGFnZS5jb250ZW50IDwtIHBhc3RlMChwYWdlLmNvbnRlbnQsIHNwcmludGYoIiAgICA8dGQgY2xhc3M9XCJ0ZGF0YSVzXCI+JXM8L3RkPlxuIiwgDQogICAgICAgICAgYXJjc3RyaW5nLCB2YWxzdHJpbmcpKQ0KICAgICAgfQ0KICAgIH0NCiAgICBpZiAoc2hvdy5mcnEpIHsNCiAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSANCiAgICAgICAgdmFsc3RyaW5nIDwtICI8c3BhbiBjbGFzcz1cIm9taXRcIj4mbHQ7bGlzdCZndDs8L3NwYW4+Ig0KICAgICAgZWxzZSB2YWxzdHJpbmcgPC0gZnJxLnZhbHVlKGluZGV4LCB4LCBkZi52YWwpDQogICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgICAgYXJjc3RyaW5nLCB2YWxzdHJpbmcpKQ0KICAgIH0NCiAgICBpZiAoc2hvdy5wcmMpIHsNCiAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSANCiAgICAgICAgdmFsc3RyaW5nIDwtICI8c3BhbiBjbGFzcz1cIm9taXRcIj4mbHQ7bGlzdCZndDs8L3NwYW4+Ig0KICAgICAgZWxzZSB2YWxzdHJpbmcgPC0gcHJjLnZhbHVlKGluZGV4LCB4LCBkZi52YWwpDQogICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgICAgYXJjc3RyaW5nLCB2YWxzdHJpbmcpKQ0KICAgIH0NCiAgICBpZiAoc2hvdy53dGQuZnJxICYmICFpcy5udWxsKHdlaWdodC5ieSkpIHsNCiAgICAgIGlmIChpcy5saXN0KHhbW2luZGV4XV0pKSANCiAgICAgICAgdmFsc3RyaW5nIDwtICI8c3BhbiBjbGFzcz1cIm9taXRcIj4mbHQ7bGlzdCZndDs8L3NwYW4+Ig0KICAgICAgZWxzZSB2YWxzdHJpbmcgPC0gZnJxLnZhbHVlKGluZGV4LCB4LCBkZi52YWwsIHdlaWdodC5ieSkNCiAgICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCBzcHJpbnRmKCIgICAgPHRkIGNsYXNzPVwidGRhdGElc1wiPiVzPC90ZD5cbiIsIA0KICAgICAgICBhcmNzdHJpbmcsIHZhbHN0cmluZykpDQogICAgfQ0KICAgIGlmIChzaG93LnByYyAmJiAhaXMubnVsbCh3ZWlnaHQuYnkpKSB7DQogICAgICBpZiAoaXMubGlzdCh4W1tpbmRleF1dKSkgDQogICAgICAgIHZhbHN0cmluZyA8LSAiPHNwYW4gY2xhc3M9XCJvbWl0XCI+Jmx0O2xpc3QmZ3Q7PC9zcGFuPiINCiAgICAgIGVsc2UgdmFsc3RyaW5nIDwtIHByYy52YWx1ZShpbmRleCwgeCwgZGYudmFsLCB3ZWlnaHQuYnkpDQogICAgICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUwKHBhZ2UuY29udGVudCwgc3ByaW50ZigiICAgIDx0ZCBjbGFzcz1cInRkYXRhJXNcIj4lczwvdGQ+XG4iLCANCiAgICAgICAgYXJjc3RyaW5nLCB2YWxzdHJpbmcpKQ0KICAgIH0NCiAgICBpZiAoIWhpZGUucHJvZ3Jlc3MpIA0KICAgICAgdXRpbHM6OnNldFR4dFByb2dyZXNzQmFyKHBiLCBjY250KQ0KICAgIHBhZ2UuY29udGVudCA8LSBwYXN0ZTAocGFnZS5jb250ZW50LCAiICA8L3RyPlxuIikNCiAgfQ0KICBpZiAoIWhpZGUucHJvZ3Jlc3MpIA0KICAgIGNsb3NlKHBiKQ0KICBwYWdlLmNvbnRlbnQgPC0gcGFzdGUocGFnZS5jb250ZW50LCAiPC90YWJsZT4iLCBzZXAgPSAiXG4iKQ0KICB0b1dyaXRlIDwtIHBhc3RlMCh0b1dyaXRlLCBzcHJpbnRmKCIlc1xuPC9ib2R5PjwvaHRtbD4iLCANCiAgICBwYWdlLmNvbnRlbnQpKQ0KICBrbml0ciA8LSBwYWdlLmNvbnRlbnQNCiAga25pdHIgPC0gZ3N1YigiY2xhc3M9IiwgInN0eWxlPSIsIGtuaXRyLCBmaXhlZCA9IFRSVUUsIHVzZUJ5dGVzID0gVFJVRSkNCiAga25pdHIgPC0gZ3N1YigiPHRhYmxlIiwgc3ByaW50ZigiPHRhYmxlIHN0eWxlPVwiJXNcIiIsIGNzcy50YWJsZSksIA0KICAgIGtuaXRyLCBmaXhlZCA9IFRSVUUsIHVzZUJ5dGVzID0gVFJVRSkNCiAga25pdHIgPC0gZ3N1Yih0YWcudGRhdGEsIGNzcy50ZGF0YSwga25pdHIsIGZpeGVkID0gVFJVRSwgDQogICAgdXNlQnl0ZXMgPSBUUlVFKQ0KICBrbml0ciA8LSBnc3ViKHRhZy50aGVhZCwgY3NzLnRoZWFkLCBrbml0ciwgZml4ZWQgPSBUUlVFLCANCiAgICB1c2VCeXRlcyA9IFRSVUUpDQogIGtuaXRyIDwtIGdzdWIodGFnLmFyYywgY3NzLmFyYywga25pdHIsIGZpeGVkID0gVFJVRSwgdXNlQnl0ZXMgPSBUUlVFKQ0KICBpZiAocmVtb3ZlLnNwYWNlcykgew0KICAgIGtuaXRyIDwtIHNqdS5ybXNwYyhrbml0cikNCiAgICB0b1dyaXRlIDwtIHNqdS5ybXNwYyh0b1dyaXRlKQ0KICAgIHBhZ2UuY29udGVudCA8LSBzanUucm1zcGMocGFnZS5jb250ZW50KQ0KICB9DQogIHN0cnVjdHVyZShjbGFzcyA9IGMoInNqVGFibGUiLCAidmlld19kZiIpLCBsaXN0KHBhZ2Uuc3R5bGUgPSBwYWdlLnN0eWxlLCANCiAgICBwYWdlLmNvbnRlbnQgPSBwYWdlLmNvbnRlbnQsIG91dHB1dC5jb21wbGV0ZSA9IHRvV3JpdGUsIA0KICAgIGhlYWRlciA9IE5VTEwsIGtuaXRyID0ga25pdHIsIGZpbGUgPSBmaWxlLCBzaG93ID0gIW5vLm91dHB1dCwgDQogICAgdXNlLnZpZXdlciA9IHVzZS52aWV3ZXIpKQ0KfQ0KDQp2aWV3X2RmMihhcmFiNCwgaGlkZS5wcm9ncmVzcyA9IFQpDQpgYGANCg0KDQo=